BSC DeFi에 대한 간단한 소개에 이어 이제 실전으로 들어가보겠습니다.

우선 web3.py를 설치하여야 합니다. 설치 방법은 아래와 같이.

 

pip install web3

 

DeFi 프로젝트에 따라서 smart contract을 만드는 방식이 다양합니다. 따라서 사이트에 맞게 필요한 smart contract 주소를 잘 찾아야합니다. 예제로 선보인 pancakeswap은 아래와 같은 구조로 구성되어 있습니다.

 

pancakeswap 풀에 있는 모든 풀은 MasterChef라는 이름의 smart contract 만들어져있습니다. 각각의 풀도 smart contract이고 각 풀에 있는 token들도 smart contract로 만들어져있습니다.

 

 

각각의 smart contract 주소는 아래와 같습니다.

 

MasterChef : 0x73feaa1eE314F8c655E354234017bE2193C9E24E
   |
  +-- Cake-BNB LP : 0xA527a61703D82139F8a06Bc30097cC9CAA2df5A6
     |
    + Cake : 0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82
    + Bnb : 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c

 

전 글에서 언급하였듯이 smart contract의 ABI가 필요합니다. bscscan에 접속하여 해당 주소를 입력한 후 ABI 값을 복사해옵니다.

 

Cake-BNB LP와 Cake, Bnb의 경우에는 Cake-BNB LP smart contract를 사용합니다. 일반적인 smart contract에 있는 함수만 사용하기 때문에 각각의 ABI 파일을 다운받을 필요가 없지만 각 contract 고유의 기능을 사용하려면 별도로 모두 받아야합니다. 이 절차가 조금 번거롭기는 합니다.

 

파이썬 프로그램으로 해당 smart contract의 값을 읽어오는 절차입니다.

 

우선 bsc network으로 Web3를 기동시킵니다. 사용하는 블럭체인에 맞는 주소를 입력해주면 됩니다.

w3 = Web3(Web3.HTTPProvider('https://bsc-dataseed.binance.org/'))

 다음으로는 검색할 pool에 대한 주소와 ABI 값을 dict구조에 추가합니다. 앞으로 여러 pool을 대상으로 검색을 할 수 있도록 dict 형태로 작업을 했습니다.

그리고 common abi도 하나 복사해두었습니다. 이건 Cake-BNB LP에서 가져온 ABI입니다.

 

이러한 정보를 바탕으로 w3.eth.contract() 함수를 호출합니다.

pools = { 
        'pancake' : 
            {   'addr':'0x73feaa1eE314F8c655E354234017bE2193C9E24E',
                'abi' : '[{"inputs":[{"internalType"...]' # 너무 길어서 생략
            },
}

# 일반적인 풀의 abi. 만약 함수명이 틀린 풀이 있으면 해당 풀의 abi로 대체
contract_common_abi = '[{"inputs":[],"payable":false, ...]' # 너무 길어서 생략

def pool_info():
    for name in pools : 
        ee = w3.eth.contract(pools[name]['addr'], abi=pools[name]['abi'])
        

 

pancakswap MasterChef ABI를 보고서 필요한 함수를 부릅니다. 이 ABI에는 pool의 갯수를 알려주는 함수가 있습니다. 풀 갯수만큼 루프를 돌리면서 본인이 staking한 풀에 채굴된 cake 수량을 출력해주는 함수입니다.

 

        # 풀의 총 갯수를 얻는다.
        poolLength = ee.functions.poolLength().call()
        for 풀 수량 만큼 :
            # 해당 풀에 deposit한 수량을 얻는다.
            user_info = ee.functions.userInfo(i, my_addr).call()
	
            # 만약 내가 staking한 pool이면
            if user_info[0] > 0 :  # for only staked pools
                # 풀에 대한 정보를 얻는다.
                poolInfo = ee.functions.poolInfo(i).call()

                # deposit한 LP 수량을 얻는다.
                deposit = user_info[0] / (10 ** 18 ) 

                # 채굴된 cake의 수량을 얻는다.
                pending_cakes = ee.functions.pendingCake(i, my_addr).call() 
                pending_cakes_real = pending_cakes/(10 ** 18 )


                # 해당 풀의 smart contract 주소를 얻는다.
                addr1 = poolInfo[0]

                # 해당 풀의 토큰의 주소와 abi로 smart contract 정보를 얻는다.
                e1 = w3.eth.contract(addr1, abi=contract_common_abi)

                # 1번 토큰의 주소를 얻은 후 smart contract 정보를 얻는다.
                token1 = e1.functions.token0().call()
                t1 = w3.eth.contract(token1, abi=contract_common_abi)

                # 1번 토큰 정보를 얻는다
                name1 = t1.functions.name().call()
                sym1 = t1.functions.symbol().call()

                # 2번 토큰의 주소를 얻은 후 smart contract 정보를 얻는다.
                token2 = e1.functions.token1().call()
                t2 = w3.eth.contract(token2, abi=contract_common_abi)

                # 2번 토큰 정보를 얻는다
                name2 = t2.functions.name().call()
                sym2 = t2.functions.symbol().call()

                print("[%6s - %6s] %10.3f   %10.3f"%(sym1, sym2, deposit, pending_cakes_real))

 

 결과를 확인해보겠습니다.

 

화면에서 보는 수량과 일치하는 값을 얻을 수 있었습니다.

이 방식을 기반으로 여러 DeFi 프로젝트의 smart contract 주소와 ABI 파일을 구하면 본인이 투자한 DeFi에서 채굴한 토큰의 수량을 바로 파악을 할 수 있을 것 같습니다.

 

다음으로 할 일은 채굴된 토큰들을 자동으로 claim하는 부분입니다. 이 또한 예제가 부실하여 아직 작업이 마무리되지 못하였습니다. 이번 주말에 작업해서 성공한다면 정리해서 올리도록 하겠습니다.

 

파이썬으로 BSC Smart contract를 다루는 예제를 발견하기 어려운데요. 이렇게 간단하게 구현할 수 있는 것을 아주 아주 힘들게 돌아온 것 같습니다. 

 

본 글에 나오는 예제는 아래 github에 있습니다.

 

github.com/multizone-quant/DeFi/blob/main/WatchingDeFi.py

반응형

설정

트랙백

댓글