Web3py에서 오류가 발생하지 않았습니다 (Remix에서 발생했습니다).

Nov 13 2020

내가 사용한 계약 :

EtherDelta (DEX)

프리덤 코인 (토큰)

내 논리는 다음과 같습니다.

두 계약을 배포 한 userA를 사용하여 100Ether를 userB로 전송 한 다음 userB invoke를 호출 depositToken하지만 transferFrom토큰 계약에 없기 때문에 fallback 함수로 이동합니다.

  function() {
    throw;
  }

분명히 그것은 던져 질 것이고, 그것은 정확히 리믹스에서 일어난 일입니다.

내가 web3py를 사용하여 바이트 코드에서이 테스트 때, 트랜잭션은 성공적 status이었다 1, 내가 선택한 경우 balanceOfEtherDelta, 그것은 진정한 가치를 반환했습니다. 나는 무엇이 잘못되었는지 모른다. 이것은 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')})

왜 내가 바이트 코드를 사용하는지 묻지 마십시오. 그것이 내 실험에 대한 요청입니다. 함수 서명에 문제가 없는지 확인할 수 있습니다.

답변

1 Ismael Nov 14 2020 at 10:47

각 계약에서 요구하는 견고성 버전을 사용한다고 가정하면 문제는 거래소에서 사용하는 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를 사용하여 transferFrombool을 반환 했는지 확인하기 때문에 호출이 되돌립니다 .