[Ethereum] 아비트라지를 위한 여정 8편 - 비율 가져오기

0xDave·2022년 10월 11일
0

Ethereum

목록 보기
43/112
post-thumbnail

SPELL/sSPELL 비율 가져오기

sSPELL은 SPELL을 스테이킹 해서 받을 수 있다. 현재 보유하고 있는sSPELL 토큰의 갯수에 따라서 사용자가 SPELL fee pool 내 자신의 지분이 어느 정도인지 알 수 있다. 현재 sSPELL과 SPELL의 비율은 1:1.3692다. 일정 비율이 지날 때 서로 스왑할 수 있도록 설계는 했지만 그 일정 비율이 어느 정도인지 항상 알고 있어야 한다.

이러한 정보는 SPELL을 스테이킹 했을 때 sSPELL을 민팅해주는 컨트랙트에서 가져와야 한다. 여기서 핵심은 (amount * totalSupply) / totalTokens; 이 부분이다. 현재 컨트랙트가 가지고 있는 SPELL 토큰의 양(totalTokens)에 비해 가지고 있는 sSPELL의 양(totalSupply)을 이용해 비율을 결정한다. 또 한가지 주목할 부분은 emit Transfer()다. emit 된 빈도수를 가지고 비율을 결정할 수 있을 것이다.

function mint(uint256 amount) public returns (bool) {
    require(msg.sender != address(0), "Zero address");
    User memory user = users[msg.sender];

    uint256 totalTokens = token.balanceOf(address(this));
    uint256 shares = totalSupply == 0 ? amount : (amount * totalSupply) / totalTokens;
    user.balance += shares.to128();
    user.lockedUntil = (block.timestamp + LOCK_TIME).to128();
    users[msg.sender] = user;
    totalSupply += shares;

    token.safeTransferFrom(msg.sender, address(this), amount);

    emit Transfer(address(0), msg.sender, shares);
    return true;
}

그렇다면 우리도 실시간으로 비율을 가져오기 위해서 노드를 돌릴 필요가 있다.

Infura

가볍게 사용하기 좋은 Infura에서 노드를 만들어보자. 홈페이지에 가입해서 CREATE NEW KEY를 통해 api key를 만든다. 이제 brownie에 적용해보자. api key를 export하고 이더리움 메인넷으로 네트워크를 변경하면 된다.

$ source .venv/bin/activate
$ export WEB3_INFURA_PROJECT_ID="" <- Infura api key 넣으면 된다.
$ brownie console --network mainnet

갯수 확인

이제 각 토큰 주소를 추가하고 얼마나 들어있는지 확인해보자.

>>> spell = Contract.from_explorer('0x090185f2135308bad17527004364ebcc2d37e5f6')
>>> sspell = Contract.from_explorer('0x26fa3fffb6efe8c1e69103acb4044c26b9a106a9')
>>> sspell.totalSupply()
21698335947692476238338032297
>>> spell.balanceOf(sspell.address)
29709488074582133650944681754

이제 비율을 계산해보면 29709488074582133650944681754/21698335947692476238338032297 = 1.3692가 나오는 것을 알 수 있다..!! 이제 비율을 자동으로 가져오는 봇을 만들어보자.


주요 로직


def main():

    try:
        network.connect("mainnet")
    except:
        sys.exit(
            "Could not connect to Ethereum! Verify that brownie lists the Ethereum (Infura) Mainnet using 'brownie networks list'"
        )

    print("\nContracts loaded:")
    spell_contract = contract_load(SPELL_CONTRACT_ADDRESS, "Token: SPELL")
    sspell_contract = contract_load(SSPELL_CONTRACT_ADDRESS, "Token: sSPELL")

    # creates a blank file, writes "0.0" to force a refresh in the main loop
    with open(FILENAME, "w") as file:
        file.write(str(0.0) + "\n")

    while True:
		#읽기모드로 파일 오픈해서 변수에 저장
        with open(FILENAME, "r") as file:
            abra_rate = float(file.read().strip())

        try:
            result = round(
                spell_contract.balanceOf(sspell_contract.address)
                / sspell_contract.totalSupply(),
                4,
            )
        except Exception as e:
            print(f"{e}")
            continue

        if abra_rate and result == abra_rate:
            pass
        else:
            print(f"Updated rate found: {result}")
            abra_rate = result
            with open(FILENAME, "w") as file:
                file.write(str(abra_rate) + "\n")

        time.sleep(60)
        
# Only executes main loop if this file is called directly
if __name__ == "__main__":
    main() 

로직은 간단하다. Brownie로 이더리움 네트워크에 연결하고 각 컨트랙트를 불러온다. 이후 빈 파일을 만들고 일정 시간마다 SPELL/sSPELL 비율을 계산해서 파일에 업데이트 한다.

파이썬 개념

with..as : with..as로 파일을 열면 close()를 따로 호출하지 않아도 된다.
strip() : 공백을 제거한다.
round( ,4) : 소수점 넷째자리까지 반올림한다.


출처 및 참고자료


  1. https://docs.abracadabra.money/
  2. Bot Building — Staking Rate Watcher
  3. [Python] with문 이해하기
profile
Just BUIDL :)

0개의 댓글