EVMHost: Fix selfdestruct with non-zero value at beneficiary and value-transfers with insufficient funds

Create a helper for transfering balance between two accounts. Check sufficient funds are available during a call-with-value.
This commit is contained in:
Alex Beregszaszi 2021-03-30 22:05:55 +01:00
parent 324caef53c
commit a54699f452
2 changed files with 19 additions and 4 deletions

View File

@ -168,12 +168,19 @@ void EVMHost::reset()
}
}
void EVMHost::transfer(evmc::MockedAccount& _sender, evmc::MockedAccount& _recipient, u256 const& _value) noexcept
{
assertThrow(u256(convertFromEVMC(_sender.balance)) >= _value, Exception, "Insufficient balance for transfer");
_sender.balance = convertToEVMC(u256(convertFromEVMC(_sender.balance)) - _value);
_recipient.balance = convertToEVMC(u256(convertFromEVMC(_recipient.balance)) + _value);
}
void EVMHost::selfdestruct(const evmc::address& _addr, const evmc::address& _beneficiary) noexcept
{
// TODO actual selfdestruct is even more complicated.
evmc::uint256be balance = accounts[_addr].balance;
transfer(accounts[_addr], accounts[_beneficiary], convertFromEVMC(accounts[_addr].balance));
accounts.erase(_addr);
accounts[_beneficiary].balance = balance;
// Record self destructs
recorded_selfdestructs.push_back({_addr, _beneficiary});
}
@ -271,8 +278,14 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept
if (value != 0 && message.kind != EVMC_DELEGATECALL && message.kind != EVMC_CALLCODE)
{
sender.balance = convertToEVMC(u256(convertFromEVMC(sender.balance)) - value);
destination.balance = convertToEVMC(u256(convertFromEVMC(destination.balance)) + value);
if (value > convertFromEVMC(sender.balance))
{
evmc::result result({});
result.status_code = EVMC_INSUFFICIENT_BALANCE;
accounts = stateBackup;
return result;
}
transfer(sender, destination, value);
}
// Populate the access access list.

View File

@ -91,6 +91,8 @@ public:
private:
evmc::address m_currentAddress = {};
void transfer(evmc::MockedAccount& _sender, evmc::MockedAccount& _recipient, u256 const& _value) noexcept;
/// Records calls made via @param _message.
void recordCalls(evmc_message const& _message) noexcept;