EthereumのContractにおいて、 Contract内部から他のContractの関数を呼び出したいケースがあります。 その時に考えられる方法としては主に以下の2つかと思います。
- ①Contract内で別のContractをnewする
- ②既にデプロイされている外部のContractを使う
今回は、②の方法について検証してみました。
①の場合は特に意識をする必要ないですが、②の場合は既にデプロイされているContractを使うため、外部から値を受け取る必要があり、今回はContractのaddress
を受取るという方法をとっています。
デプロイ済みの(共通利用される)Contract
pragma solidity ^0.4.11; contract MyToken { uint256 public totalSupply; mapping (address => uint256) public balanceOf; function MyToken(address owner) { totalSupply = 10000; balanceOf[owner] = 1000; } function transferFrom(address _from, address _to, uint256 _value) returns (bool success) { if (_to == 0x0) revert(); if (balanceOf[_from] < _value) revert(); if (balanceOf[_to] + _value < balanceOf[_to]) revert(); balanceOf[_from] -= _value; balanceOf[_to] += _value; return true; } }
- 簡単なTokenを作成しています
- このTokenは、送信用の関数として
transferFrom
を持っています - このTokenは既にデプロイされている想定でこのContractのアドレスを使用します
- 簡単のため、コンストラクタで渡されるアカウントのアドレスに1000Tokenを渡しています
MyTokenを利用するContract
pragma solidity ^0.4.11; // 呼び出す対象のコンストラクタはimportする必要がある import './MyToken.sol'; contract TokenCaller { MyToken public token; function TokenCaller(address _token) { require(_token != 0x0); // コンストラクタでアドレスからMyTokenObjectに変換 token = MyToken(_token); } function transfer(address from, address to, uint256 total) returns (bool) { // tokenからtransferFromを実行する return token.transferFrom(from, to, total); } }
- Tokenを利用する側のContractです
- コンストラクタでTokenのアドレスを受取りTokenのオブジェクトを生成します
- 関数
transfer
は、生成したTokenのtransfer
を内部で呼び出しTokenの送信処理を行います
動作確認
動作確認は、truffleを使ってtestRPC上で実行しています。
var TokenCaller = artifacts.require('../contracts/TokenCaller.sol'); var MyToken = artifacts.require('../contracts/MyToken.sol'); contract('TokenCaller', function(accounts) { it ('test', async function() { // MyTokenのデプロイ let token = await MyToken.new(accounts[1]) // Callerのデプロイ let caller = await TokenCaller.new(token.address) // Tokenの送り先のaccount[2]にtokenがないことを確認 console.log(await token.balanceOf.call(accounts[2])); // account1からaccount2にトークンを100送る await caller.transfer(accounts[1], accounts[2], 100) // account2のトークンを確認 console.log(await token.balanceOf.call(accounts[2])); }); });
結果
Contract: TokenCaller { [String: '0'] s: 1, e: 0, c: [ 0 ] } { [String: '100'] s: 1, e: 2, c: [ 100 ] }
- account2にトークンが送られていることが確認できました。
参考
https://dappsforbeginners.wordpress.com/tutorials/interactions-between-contracts/