Web3py에서 오류가 발생하지 않았습니다 (Remix에서 발생했습니다).
내가 사용한 계약 :
EtherDelta (DEX)
프리덤 코인 (토큰)
내 논리는 다음과 같습니다.
두 계약을 배포 한 userA를 사용하여 100Ether를 userB로 전송 한 다음 userB invoke를 호출 depositToken
하지만 transferFrom
토큰 계약에 없기 때문에 fallback 함수로 이동합니다.
function() {
throw;
}
분명히 그것은 던져 질 것이고, 그것은 정확히 리믹스에서 일어난 일입니다.
내가 web3py를 사용하여 바이트 코드에서이 테스트 때, 트랜잭션은 성공적 status
이었다 1
, 내가 선택한 경우 balanceOf
EtherDelta, 그것은 진정한 가치를 반환했습니다. 나는 무엇이 잘못되었는지 모른다. 이것은 web3py 자체에 관한 것입니까?
다음은 테스트 코드입니다. ganache-cli를 테스트 넷으로 사용했습니다.
import json
from tqdm import trange
from web3 import Web3, HTTPProvider, IPCProvider, WebsocketProvider
account1 = "0x827A309CCf3a92F259E2081240Da9A503495F101"
account2 = "0x52EDd47566812fb01BdAA58d58630fe95C757CdD"
w3 = Web3(HTTPProvider('http://127.0.0.1:8545',request_kwargs={'timeout':600}))
DexBinCode =""
#I'm omitting this as it's too long, but I'm sure that the deployment is successful.
dexDeploymentReceipt = w3.eth.sendTransaction({'from':account1,'value':0,'data':DexBinCode,'gas':100000000})
dexDeployHash = Web3.toHex(dexDeploymentReceipt)
truedexDeploymentReceipt = w3.eth.getTransactionReceipt(dexDeployHash)
dex_address = truedexDeploymentReceipt['contractAddress']
TokenBinCode = ""
# Same as the DEX contract
# Deploy token contract
try:
tokenDeploymentReceipt = w3.eth.sendTransaction({'from':account1,'value':0,'data':TokenBinCode,'gas':100000000})
tokenDeployHash = Web3.toHex(tokenDeploymentReceipt)
truetokenDeploymentReceipt = w3.eth.getTransactionReceipt(tokenDeployHash)
token_address = truetokenDeploymentReceipt['contractAddress']
except:
print('error1')
# Transfer 100 Ether from account1 to account2
try:
setupBinCode = "0xa9059cbb000000000000000000000000"+account2.replace('0x','')+"0000000000000000000000000000000000000000000000000000000000000064"
setupTransferReceipt = w3.eth.sendTransaction({'from':account1,'to':token_address,'value':0,'data':setupBinCode,'gas':100000000})
setupTransferHash = Web3.toHex(setupTransferReceipt)
truesetupTransferReceipt = w3.eth.getTransactionReceipt(setupTransferHash)
except:
print('error2')
# depositToken with account2
try:
depositBinCode = "0x338b5dea000000000000000000000000"+token_address.replace('0x','')+"00000000000000000000000000000000000000000000000000000000000001f4"
balanceBinCode = "0xf7888aec000000000000000000000000"+token_address.replace('0x','')+"000000000000000000000000"+account2.replace('0x','')
depositReceipt = w3.eth.sendTransaction({'from':account2,'to':dex_address,'value':0,'data':depositBinCode,'gas':1000000000})
depositHash = Web3.toHex(depositReceipt)
trueDepositReceipt = w3.eth.getTransactionReceipt(depositHash)
print(trueDepositReceipt)
balance = w3.eth.call({'from':account2,'to':dex_address,'data':balanceBinCode})
balance = Web3.toHex(balance)
print(balance)
if balance !='0x00000000000000000000000000000000000000000000000000000000000001f4':
print('error6')
except:
print('error7')
결과 trueDepositReceipt
:
AttributeDict({'transactionHash': HexBytes('0xeb4e17dc0025e2edb8c2108944b3d521b71c0d527acd97f1c2fbfddb331bd76f'), 'transactionIndex': 0, 'blockHash': HexBytes('0xc71c82f0d38fa2c8ac6dfce57068dd93b1420d23e4b6a99ecbe5d269d56298b6'), 'blockNumber': 80, 'from': '0x52EDd47566812fb01BdAA58d58630fe95C757CdD', 'to': '0x552044ff5ca9F9094754C1ed53fD84Ac182eCC9B', 'gasUsed': 50181, 'cumulativeGasUsed': 50181, 'contractAddress': None, 'logs': [AttributeDict({'logIndex': 0, 'transactionIndex': 0, 'transactionHash': HexBytes('0xeb4e17dc0025e2edb8c2108944b3d521b71c0d527acd97f1c2fbfddb331bd76f'), 'blockHash': HexBytes('0xc71c82f0d38fa2c8ac6dfce57068dd93b1420d23e4b6a99ecbe5d269d56298b6'), 'blockNumber': 80, 'address': '0x552044ff5ca9F9094754C1ed53fD84Ac182eCC9B', 'data': '0x00000000000000000000000080eff541e03059f920931ab7d93c942e2da3052700000000000000000000000052edd47566812fb01bdaa58d58630fe95c757cdd00000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000000001f4', 'topics': [HexBytes('0xdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7')], 'type': 'mined'})], 'status': 1, 'logsBloom': HexBytes('0x00002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000002000000000000000000000000000000000')})
왜 내가 바이트 코드를 사용하는지 묻지 마십시오. 그것이 내 실험에 대한 요청입니다. 함수 서명에 문제가 없는지 확인할 수 있습니다.
답변
각 계약에서 요구하는 견고성 버전을 사용한다고 가정하면 문제는 거래소에서 사용하는 solc 0.4.9에에서 반환 된 가치 부족을 무시하는 버그가 있다는 것 transferFrom
입니다.
교환 transferFrom
은 토큰에서 호출 하고 false를 반환하면 되돌립니다.
if (!Token(token).transferFrom(msg.sender, this, amount)) throw;
그러나 토큰이 구현되지 않으므로 transferFrom
대신 토큰의 대체가 호출됩니다.
function () public payable {
create(msg.sender);
}
create
성공을 호출하고 아무것도 반환 하지 않습니다 . 그러나 거래소는 부울을 반환 할 것으로 예상하고 있습니다.
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {}
컴파일러의 버그는 입력 및 출력 매개 변수 모두에 대해 동일한 메모리 버퍼를 사용한다는 것입니다. 따라서 토큰이 아무것도 반환하지 않기 때문에 입력은 출력으로 평가되고 exchange의 경우 transferFrom은 true를 반환 합니다 .
0.4.26과 같은 최신 solc 버전으로 컴파일하면 새로운 opcode RETURNDATASIZE를 사용하여 transferFrom
bool을 반환 했는지 확인하기 때문에 호출이 되돌립니다 .