계약 배포하기
Brownie가 로드될 때마다 프로젝트를 자동으로 컴파일하고 배포 가능한 각 계약에 대한 ContractContainer
객체를 만듭니다. 이 객체는 개별 배포에 액세스하기 위한 컨테이너로 사용됩니다. 또한 새 계약을 배포하는 데에도 사용됩니다.
>>> Token
[]
>>> type(Token)
<class 'brownie.network.contract.ContractContainer'>
>>> Token.deploy
<ContractConstructor object 'Token.constructor(string _symbol, string _name, uint256 _decimals, uint256 _totalSupply)'>
ContractContainer.deploy
함수는 새로운 스마트 컨트랙트를 배포하는 데 사용됩니다.
>>> Token.deploy
<ContractConstructor object 'Token.constructor(string _symbol, string _name, uint256 _decimals, uint256 _totalSupply)'>
계약 생성자 전달인자 및 거래 매개변수 사전과 함께 호출해야 하며, 이는 from
필드를 포함하는 것이 필요하며 해당 필드는 계약을 배포할 Account
를 지정합니다.
>>> Token.deploy("Test Token", "TST", 18, 1e23, {'from': accounts[1]})
Transaction sent: 0x2e3cab83342edda14141714ced002e1326ecd8cded4cd0cf14b2f037b690b976
Transaction confirmed - block: 1 gas spent: 594186
Contract deployed at: 0x5419710735c2D6c3e4db8F30EF2d361F70a4b380
<Token Contract object '0x5419710735c2D6c3e4db8F30EF2d361F70a4b380'>
ContractContainer.deploy
를 호출하면 ProjectContract
객체가 반환됩니다. 반환된 객체는 ContractContainer
에도 추가됩니다.
>>> t = Token.deploy("Test Token", "TST", 18, 1e23, {'from': accounts[1]})
Transaction sent: 0x2e3cab83342edda14141714ced002e1326ecd8cded4cd0cf14b2f037b690b976
Transaction confirmed - block: 1 gas spent: 594186
Contract deployed at: 0x5419710735c2D6c3e4db8F30EF2d361F70a4b380
<Token Contract object '0x5419710735c2D6c3e4db8F30EF2d361F70a4b380'>
>>> t
<Token Contract object '0x5419710735c2D6c3e4db8F30EF2d361F70a4b380'>
>>> Token
[<Token Contract object '0x5419710735c2D6c3e4db8F30EF2d361F70a4b380'>]
링크되지 않은 라이브러리
컨트랙트가 라이브러리를 필요로 하는 경우, 브라우니는 가장 최근에 배포된 라이브러리에 자동으로 링크합니다. 필요한 라이브러리가 아직 배포되지 않았으면 UndeployedLibrary
예외가 발생합니다.
>>> MetaCoin.deploy({'from': accounts[0]})
File "brownie/network/contract.py", line 167, in __call__
f"Contract requires '{library}' library but it has not been deployed yet"
UndeployedLibrary: Contract requires 'ConvertLib' library but it has not been deployed yet
>>> Convert.deploy({'from': accounts[0]})
Transaction sent: 0xff3f5cff35c68a73658ad367850b6fa34783b4d59026520bd61b72b6613d871c
ConvertLib.constructor confirmed - block: 1 gas used: 95101 (48.74%)
ConvertLib deployed at: 0x08c4C7F19200d5636A1665f6048105b0686DFf01
<ConvertLib Contract object '0x08c4C7F19200d5636A1665f6048105b0686DFf01'>
>>> MetaCoin.deploy({'from': accounts[0]})
Transaction sent: 0xd0969b36819337fc3bac27194c1ff0294dd65da8f57c729b5efd7d256b9ecfb3
MetaCoin.constructor confirmed - block: 2 gas used: 231857 (69.87%)
MetaCoin deployed at: 0x8954d0c17F3056A6C98c7A6056C63aBFD3e8FA6f
<MetaCoin Contract object '0x8954d0c17F3056A6C98c7A6056C63aBFD3e8FA6f'>
계약과 상호작용하기
계약을 배포한 후에는 호출과 트랜잭션을 통해 상호작용할 수 있습니다.
- 트랜잭션은 네트워크에 방송되어 블록체인에 기록됩니다. 실행에는 이더가 필요하며 블록체인의 상태를 변경할 수 있습니다.
- 호출은 트랜잭션을 방송하지 않고 네트워크에서 코드를 실행하는 데 사용됩니다. 실행에는 비용이 들지 않으며 블록체인의 상태를 변경할 수 없습니다. 호출은 일반적으로 게터 메서드를 사용하여 계약에서 저장소 값을 검색하는 데 사용됩니다.
계약 내의 모든 공개 함수에 대해 호출하거나 트랜잭션을 보낼 수 있습니다. 그러나 코드에 따라 항상 선호되는 방법이 있습니다.
- Solidity에서 호출 가능한 메서드는
view
또는pure
로 표시됩니다.
- Vyper에서 호출 가능한 메서드에는
@constant
데코레이터가 포함됩니다.
모든 공개 계약 메서드는 ProjectContract
객체에서 동일한 이름의 클래스 메서드를 통해 사용할 수 있습니다.
>>> Token[0].transfer
<ContractTx object 'transfer(address _to, uint256 _value)'>
>>> Token[0].balanceOf
<ContractCall object 'balanceOf(address _owner)'>
계약 소스에 NatSpec 문서가 포함되어 있으면 ContractCall.info
메소드를 통해 볼 수 있습니다:
>>> Token[0].transfer.info()
transfer(address _to, uint256 _value)
@dev transfer token for a specified address
@param _to The address to transfer to.
@param _value The amount to be transferred.
거래
상태 변경 컨트랙트 메소드는 ContractTx
객체를 통해 호출됩니다. 이 객체는 트랜잭션을 수행하고 TransactionReceipt
를 반환합니다.
옵션으로 트랜잭션 매개변수의 딕셔너리를 마지막 인자로 포함할 수 있습니다. 이를 수행하지 않거나 매개변수 내에서 from
값을 지정하지 않으면, 트랜잭션은 컨트랙트를 배포한 동일한 주소에서 전송됩니다.
>>> Token[0].transfer(accounts[1], 1e18, {'from': accounts[0]})
Transaction sent: 0x6e557594e657faf1270235bf4b3f27be7f5a3cb8a9c981cfffb12133cbaa165e
Token.transfer confirmed - block: 4 gas used: 51019 (33.78%)
<Transaction object '0x6e557594e657faf1270235bf4b3f27be7f5a3cb8a9c981cfffb12133cbaa165e'>
거래 없이 컨트랙트 메소드를 호출하려면 ContractTx.call
메소드를 사용하세요.
>>> Token[0].transfer.call(accounts[1], 1e18, {'from': accounts[0]})
True
거래 매개 변수
계약에 대한 거래를 실행할 때, 마지막 입력으로 거래 매개 변수의 dict
를 선택적으로 포함시킬 수 있습니다. 이것은 다음 값을 포함할 수 있습니다:
- from: 거래를 보내는 계정. 지정하지 않으면, 거래는 계약을 배포한 계정에서 보내집니다.
- gas_limit: wei 단위로 거래 실행에 대한 가스 제공량입니다. 지정하지 않으면, 가스 제한은 web3.eth.estimate_gas를 사용하여 결정됩니다.
- gas_buffer: 가스 제한을 자동으로 설정할 때 web3.eth.estimate_gas에 적용되는 배율입니다. gas_limit 및 gas_buffer 는 동시에 지정할 수 없습니다.
- gas_price: wei 단위로 레거시 거래의 가스 가격입니다. 지정하지 않으면, 가스 가격은 web3.eth.gas_price에 따라 설정됩니다.
- max_fee: 동적 수수료 거래의 가스 당 최대 수수료입니다. priority_fee: 동적 수수료 거래의 가스 당 최대 우선 순위 수수료입니다.
- amount: wei 단위로 거래에 포함될 이더의 양입니다.
- nonce: 거래의 nonce 값입니다. 지정하지 않으면, 보내는 사람의 대기 중인 거래를 고려하여 web3.eth.get_transaction_count에 따라 nonce가 설정됩니다.
- required_confs: TransactionReceipt가 처리되기 전에 필요한 확인 횟수입니다. 지정하지 않으면, 기본값은 1번의 확인입니다. 0이 지정되면, 즉시 대기 중인 TransactionReceipt를 반환하고, 별도의 스레드에서 확인을 기다립니다.
- allow_revert: 거래가 예상되는 경우 전파되어야 하는지 여부를 나타내는 부울입니다. 설정되지 않으면, 개발 환경에서 되돌리기 허용, 실제 환경에서는 되돌리기 금지가 기본 동작입니다.
모든 통화 정수 값은 Wei
에 의해 변환될 문자열로도 지정할 수 있습니다.
from
필드가 문자열로 지정된 어떤 주소든 사용할 수 있습니다. 이렇게 하면 해당 주소의 개인 키 없이 거래를 브로드캐스트할 수 있습니다. 심지어는 계약에서 거래를 보낼 수도 있습니다!호출
상태를 변경하지 않는 계약 메서드는 ContractCall
객체를 통해 호출됩니다. 이 객체는 거래를 브로드캐스트하지 않고 계약 메서드를 호출하고 결과를 반환합니다.
>>> Token[0].balanceOf(accounts[0])
1000000000000000000000
거래를 통해 메서드에 액세스하려면 ContractCall.transact
을 사용할 수 있습니다.
>>> tx = Token[0].balanceOf.transact(accounts[0])
Transaction sent: 0xe803698b0ade1598c594b2c73ad6a656560a4a4292cc7211b53ffda4a1dbfbe8
Token.balanceOf confirmed - block: 3 gas used: 23222 (18.85%)
<Transaction object '0xe803698b0ade1598c594b2c73ad6a656560a4a4292cc7211b53ffda4a1dbfbe8'>
>>> tx.return_value
1000000000000000000000
프로젝트 외부 컨트랙트
라이브 환경(Live Environment) 또는 개발용 포크(forked development network)에서 작업할 때, 배포된 컨트랙트에 상호작용하기 위해 Contract
객체를 생성할 수 있습니다.
Contract
객체는 프로젝트의 interfaces/
폴더 내 인터페이스로부터 생성하거나, 블록 익스플로러나 ethPM 레지스트리와 같은 원격 소스에서 정보를 가져와 생성할 수 있습니다.
로컬 인터페이스 사용
InterfaceContainer
객체(별칭 interface
)는 프로젝트의 interfaces/
폴더 내 인터페이스에 대한 접근을 제공합니다.
예를 들어, 인터페이스 이름이 Dai
인 컨트랙트에서 Contract
객체를 생성하려면:
>>> interface.Dai
<InterfaceConstructor 'Dai'>
>>> interface.Dai("0x6B175474E89094C44Da98b954EedeAC495271d0F")
<Dai Contract object '0x6B175474E89094C44Da98b954EedeAC495271d0F'>
딕셔너리 형태로 된 ABI에서 인스턴스를 생성하는 Contract.from_abi
클래스 메서드를 사용할 수도 있습니다:
>>> Contract.from_abi("Token", "0x79447c97b6543F6eFBC91613C655977806CB18b0", abi)
<Token Contract object '0x79447c97b6543F6eFBC91613C655977806CB18b0'>
원격 소스에서 가져오기
계약 객체는 원격 소스에서 데이터를 가져와서 생성할 수도 있습니다. 예를 들어, Etherscan에 쿼리를 보내어 객체를 생성하는 데 사용하는 Contract.from_explorer
을 사용하세요:
>>> Contract.from_explorer("0x6b175474e89094c44da98b954eedeac495271d0f")
Fetching source of 0x6B175474E89094C44Da98b954EedeAC495271d0F from api.etherscan.io...
<Dai Contract '0x6B175474E89094C44Da98b954EedeAC495271d0F'>
세션 간 계약 유지
Contract
객체를 만드는 데 사용되는 데이터는 로컬 데이터베이스에 저장되어 세션 간에 지속됩니다. 클래스 메서드를 통해 초기 생성 후, 주소를 사용하여 Contract
객체를 다시 만들 수 있습니다:
>>> Contract("0x6b175474e89094c44da98b954eedeac495271d0f")
<Dai Contract '0x6B175474E89094C44Da98b954EedeAC495271d0F'>
또한, Contract.set_alias
를 사용하여 빠른 액세스를 위한 별칭을 만들 수 있습니다. 별칭은 세션 간에도 유지됩니다.
>>> contract = Contract("0x6b175474e89094c44da98b954eedeac495271d0f")
>>> contract.set_alias('dai')
>>> Contract('dai')
<Dai Contract '0x6B175474E89094C44Da98b954EedeAC495271d0F'>
'블록체인 (Block Chain) > 이더리움' 카테고리의 다른 글
[브라우니 (Brownie)] 12. 블록체인과 상호작용하기 (0) | 2023.06.16 |
---|---|
[브라우니 (Brownie)] 11. 트랜잭션 가스 가격 설정하기 (0) | 2023.06.16 |
[브라우니 (Brownie)] 9. 계정으로 작업하기 (0) | 2023.06.16 |
[브라우니 (Brownie)] 8. 브라우니 GUI (0) | 2023.06.16 |
[브라우니 (Brownie)] 7. 브라우니 패키지 관리자 (0) | 2023.06.16 |