🚨 주의: 검증된 컨트랙트가 아닌 ABI와 상호작용하는 것은 매우 위험합니다. 절대 추천하지 않으며 항상 DYOR 하시기 바랍니다.
Brownie에서 Contract.from_explorer()
컨트랙트를 불러올 때 가끔 안 될 때가 있다. 원인은 explorer에 컨트랙트의 소스코드가 공개되지 않았기 때문이다. 소스코드를 볼 수 없는 컨트랙트와 상호작용은 위험하기 때문에 이를 방지하는 것일 수 있다. 특히 지금까지 예로 들었던 아발란체 메인넷이 아닌 다른 체인에서 컨트랙트를 불러올 때 이런 경우가 종종 있다.
이럴 때는 ABI
를 통해 컨트랙트와 상호작용 할 수 있다. 하지만 이는 매우 위험하며, 트랜잭션을 요청하는 순간 지갑의 모든 자산이 탈취당할 수 있다. 따라서 이러한 위험을 인지해야 한다. sSPELL
의 컨트랙트는 아비트럼 네트워크에서 검증된 상태다. 하지만 SPELL
은 검증되지 않았기 때문에 Brownie에서 사용하려면 ABI
를 활용해야 한다. ABI는 low level language 단위의 API 개념이라 할 수 있다. ABI를 활용해서 컨트랙트 내의 함수를 호출하거나 데이터를 얻을 수 있다. 아래는 ERC-20의 표준 ABI다. 각 항목을 자세히 보면 함수의 이름과 파라미터, 리턴값과 선언된 형태 등을 알 수 있다.
[
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_spender",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "approve",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_from",
"type": "address"
},
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transferFrom",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [
{
"name": "",
"type": "uint8"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
}
],
"name": "balanceOf",
"outputs": [
{
"name": "balance",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [
{
"name": "",
"type": "string"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "_owner",
"type": "address"
},
{
"name": "_spender",
"type": "address"
}
],
"name": "allowance",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"payable": true,
"stateMutability": "payable",
"type": "fallback"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "owner",
"type": "address"
},
{
"indexed": true,
"name": "spender",
"type": "address"
},
{
"indexed": false,
"name": "value",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"name": "from",
"type": "address"
},
{
"indexed": true,
"name": "to",
"type": "address"
},
{
"indexed": false,
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
}
]
아비트럼 네트워크에 접속
$ brownie console --network arbitrum-main
json을 임포트하고 ERC-20 ABI를 가져온다.
>>> import json
>>> ERC20_ABI = json.loads("""[ABI 복붙]""")
Contract.from_abi
를 이용해서 해당 컨트랙트를 변수에 담는다.
>>> spell = Contract.from_abi(name="SPELL Token", address="0x3e6648c5a70a150a88bce65f4ad4d506fe15d2af", abi=ERC20_ABI)
이제 기존에 컨트랙트를 이용했던 것처럼 그대로 이용할 수 있다!
>>> spell.name()
'Spell Token'
>>> spell.symbol()
'SPELL'
>>> spell.decimals()
18