Skip to content

Commit

Permalink
add one more DSL test and test deductedRefund=Min(futureRefund, gasUs…
Browse files Browse the repository at this point in the history
…ed/2)
  • Loading branch information
fedejinich committed Sep 16, 2021
1 parent f649011 commit 7db3b4e
Show file tree
Hide file tree
Showing 10 changed files with 244 additions and 145 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public String estimateGas(CallArguments args) {
ProgramResult programResult = executor.getResult();

long newGasNeeded = programResult.movedRemainingGasToChild() ?
programResult.getGasUsed() + programResult.getDeductedRefund() : // then we need to count the deductedRefunds
programResult.getGasUsed() + programResult.getDeductedRefund() :
programResult.getMaxGasUsed(); // because deductedRefund can never be higher than gasUsed/2, we can just take the relative upper bound

estimation = TypeConverter.toQuantityJsonHex(newGasNeeded);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,7 @@ private long refundGas() {
// The actual gas subtracted is equal to half of the future refund
long gasRefund = Math.min(result.getFutureRefund(), result.getGasUsed() / 2);
result.addDeductedRefund(gasRefund);
result.setGasUsedBeforeRefunds(result.getGasUsed());

gasLeftover = activations.isActive(ConsensusRule.RSKIP136) ?
GasCost.add(gasLeftover, gasRefund) :
Expand Down
1 change: 0 additions & 1 deletion rskj-core/src/main/java/org/ethereum/vm/VM.java
Original file line number Diff line number Diff line change
Expand Up @@ -1557,7 +1557,6 @@ private MessageCall getMessageCall(DataWord gas, DataWord codeAddress, Activatio
spendOpCodeGas();

// the gas needed for estimateGas will be given by gasUsed (our new lower bound)
// because it'll use the transaction gasLimit
boolean passedRemainingGasToChild = calleeGas == remainingGas;
if(passedRemainingGasToChild) {
LOGGER_FEDE.error("movedRemainingGasToChild");
Expand Down
14 changes: 14 additions & 0 deletions rskj-core/src/main/java/org/ethereum/vm/program/ProgramResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,15 @@
public class ProgramResult {

private static final Logger LOGGER_FEDE = LoggerFactory.getLogger("fede");

// useful to estimateGas, sometimes the estimatedGas matches the maximum gasUsed
private long maxGasUsed = 0;

// this field it's useful to test if the deductedRefund value is less than the half of the gasUsed
private long gasUsedBeforeRefunds = 0;

private String id;

public ProgramResult(){
String s = String.valueOf(new Random().nextInt());
id = s.substring(s.length() - 4);
Expand Down Expand Up @@ -322,4 +328,12 @@ public List<LogInfo> logsFromNonRejectedTransactions() {
.filter(logInfo -> !logInfo.isRejected())
.collect(Collectors.toList());
}

public void setGasUsedBeforeRefunds(long gasUsedBeforeRefunds) {
this.gasUsedBeforeRefunds = gasUsedBeforeRefunds;
}

public long getGasUsedBeforeRefunds() {
return gasUsedBeforeRefunds;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ public void estimateGas_gasCap() throws FileNotFoundException, DslProcessorExcep
* */
@Test
public void estimateGas_callWithValuePlusSStoreRefund() throws FileNotFoundException, DslProcessorException {
World world = World.processedWorld("dsl/eth_module/estimateGas/callWithValuePlusSstoreRefundRefactor.txt");
World world = World.processedWorld("dsl/eth_module/estimateGas/callWithValuePlusSstoreRefund.txt");

TransactionReceipt contractDeployReceipt = world.getTransactionReceiptByName("tx01");
String contractAddress = contractDeployReceipt.getTransaction().getContractAddress().toHexString();
Expand Down Expand Up @@ -440,6 +440,81 @@ public void estimateGas_nestedCallsWithValueGasRetainAndStorageRefund() throws F
long estimatedGas = estimateGas(eth, args);
LOGGER_FEDE.error("---------------------END ESTIMATE--------------------");
assertTrue(callConstant.getDeductedRefund() > 0);
assertEquals(callConstant.getGasUsedBeforeRefunds() / 2, callConstant.getDeductedRefund());
assertEquals(callConstantGasUsed + callConstant.getDeductedRefund(), estimatedGas);

args.setGas(TypeConverter.toQuantityJsonHex(callConstantGasUsed));
assertFalse(runWithArgumentsAndBlock(eth, args, block));

args.setGas(TypeConverter.toQuantityJsonHex(estimatedGas));
assertTrue(runWithArgumentsAndBlock(eth, args, block));

args.setGas(TypeConverter.toQuantityJsonHex(estimatedGas - 1));
assertFalse(runWithArgumentsAndBlock(eth, args, block));
}

/**
* Send 1 rBTC accross three contracts, then the last contract frees a storage cell and does a CALL with value
* */
@Test
public void estimateGas_nestedCallsWithValueFixedGasRetainAndStorageRefund() throws FileNotFoundException, DslProcessorException {
World world = World.processedWorld("dsl/eth_module/estimateGas/nestedCallsWithValueStorageRefundAndFixedGas.txt");

TransactionReceipt contractDeployA = world.getTransactionReceiptByName("tx01");
String contractAddressA = contractDeployA.getTransaction().getContractAddress().toHexString();
byte[] status = contractDeployA.getStatus();

assertNotNull(status);
assertEquals(1, status.length);
assertEquals(0x01, status[0]);
assertEquals("6252703f5ba322ec64d3ac45e56241b7d9e481ad", contractAddressA);

TransactionReceipt contractDeployB = world.getTransactionReceiptByName("tx02");
String contractAddressB = contractDeployB.getTransaction().getContractAddress().toHexString();
byte[] status2 = contractDeployB.getStatus();

assertNotNull(status2);
assertEquals(1, status2.length);
assertEquals(0x01, status2[0]);
assertEquals("56aa252dd82173789984fa164ee26ce2da9336ff", contractAddressB);

TransactionReceipt contractDeployC = world.getTransactionReceiptByName("tx03");
String contractAddressC = contractDeployC.getTransaction().getContractAddress().toHexString();
byte[] status3 = contractDeployC.getStatus();

assertNotNull(status3);
assertEquals(1, status3.length);
assertEquals(0x01, status3[0]);
assertEquals("27444fbce96cb2d27b94e116d1506d7739c05862", contractAddressC);

EthModule eth = EthModuleUtils.buildBasicEthModule(world);
Block block = world.getBlockChain().getBestBlock();

// call callAddressWithValue, it should start the nested calls
final CallArguments args = new CallArguments();
args.setTo(contractAddressA);
args.setValue(TypeConverter.toQuantityJsonHex(1));
args.setNonce(TypeConverter.toQuantityJsonHex(6));
args.setGas(TypeConverter.toQuantityJsonHex(BLOCK_GAS_LIMIT));
args.setData("fb60f709"); // callAddressWithValue()

ProgramResult callConstant = eth.callConstant(args, block);
List<InternalTransaction> internalTransactions = callConstant.getInternalTransactions();

assertTrue(internalTransactions.stream().allMatch(i -> i.getValue().equals(Coin.valueOf(1))));
assertEquals(3, internalTransactions.size());
assertEquals(3, callConstant.getLogInfoList().size());
assertEvents(callConstant, "NestedCallWV", 2);
assertEvents(callConstant, "LastCall", 1);


long callConstantGasUsed = callConstant.getGasUsed();

LOGGER_FEDE.error("---------------------START ESTIMATE--------------------");
long estimatedGas = estimateGas(eth, args);
LOGGER_FEDE.error("---------------------END ESTIMATE--------------------");
assertTrue(callConstant.getDeductedRefund() > 0);
assertEquals(callConstant.getGasUsedBeforeRefunds() / 2, callConstant.getDeductedRefund());
assertEquals(callConstantGasUsed + callConstant.getDeductedRefund(), estimatedGas);

args.setGas(TypeConverter.toQuantityJsonHex(callConstantGasUsed));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,35 @@ pragma solidity >=0.6.0 <0.9.0;

// import "hardhat/console.sol";

contract ValueTransfer {
function callSstoreClearWithValue(address payable sstoreClearAddress) public payable {
// payable(sstoreClearAddress).transfer(msg.value);
SStoreClear s = SStoreClear(sstoreClearAddress);
s.receiveAndClearStorage{value: msg.value}();
}
}

contract SStoreClear {
contract SStoreCallWithValue {
uint[100] public values;

event Received(address, uint);
event StorageState(uint, uint);

function receiveAndClearStorage() external payable {
emit Received(msg.sender, msg.value);
values[1] = 0;
emit StorageState(1, values[1]);
constructor() {
values[1] = 42;
}

function initStorage() public {
values[1] = 42;
}

function isStorageInit() view public returns (bool) {
return values[1] == 42;
function clearStorageAndSendValue() public payable {
values[1] = 0;
payable(address(this)).transfer(1);
}

fallback () external payable { }
}
end

account_new acc1 20000000

# Deploy ValueTransfer
# Deploy SStoreCallWithValue

transaction_build tx01
sender acc1
receiverAddress 00
value 0
data 608060405234801561001057600080fd5b5060ff8061001f6000396000f3fe608060405260043610601b5760003560e01c8062c6f1e6146020575b600080fd5b605f60048036036020811015603457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506061565b005b60008190508073ffffffffffffffffffffffffffffffffffffffff1663830136a6346040518263ffffffff1660e01b81526004016000604051808303818588803b15801560ad57600080fd5b505af115801560c0573d6000803e3d6000fd5b5050505050505056fea2646970667358221220162bdf1fffa9fb7218e7e20afb5c8c3d774ff5920a1b4a46a446f934c74459d364736f6c63430007030033
data 608060405234801561001057600080fd5b50602a600060016064811061002157fe5b018190555061016e806100356000396000f3fe6080604052600436106100385760003560e01c80635b3f81401461003b5780635e383d211461004557806394b3f5ee1461009457610039565b5b005b6100436100ab565b005b34801561005157600080fd5b5061007e6004803603602081101561006857600080fd5b8101908080359060200190929190505050610109565b6040518082815260200191505060405180910390f35b3480156100a057600080fd5b506100a9610121565b005b6000806001606481106100ba57fe5b01819055503073ffffffffffffffffffffffffffffffffffffffff166108fc60019081150290604051600060405180830381858888f19350505050158015610106573d6000803e3d6000fd5b50565b6000816064811061011657fe5b016000915090505481565b602a600060016064811061013157fe5b018190555056fea26469706673582212204f4296fafbb59e65b8ab38addc7f71380bbcba3f71112e6f4c4304298ed663c864736f6c63430007030033
gas 2000000
build

Expand All @@ -53,68 +43,22 @@ block_build b01
block_connect b01
assert_best b01

# Deploy SStoreClear
# call clearStorageAndSendValue()

transaction_build tx02
sender acc1
nonce 1
value 0
data 608060405234801561001057600080fd5b5061021a806100206000396000f3fe60806040526004361061003f5760003560e01c806326d7ae02146100445780635e383d2114610071578063830136a6146100c057806394b3f5ee146100ca575b600080fd5b34801561005057600080fd5b506100596100e1565b60405180821515815260200191505060405180910390f35b34801561007d57600080fd5b506100aa6004803603602081101561009457600080fd5b81019080803590602001909291905050506100fb565b6040518082815260200191505060405180910390f35b6100c8610113565b005b3480156100d657600080fd5b506100df6101cd565b005b6000602a60006001606481106100f357fe5b015414905090565b6000816064811061010857fe5b016000915090505481565b7f88a5966d370b9919b20f3e2c13ff65706f196a4e32cc2c12bf57088f885258743334604051808373ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a160008060016064811061017757fe5b01819055507ff81e688351a0b14d35e19a1855b78412f6b2dba0f95d0fac876a8488f7f812f2600160006001606481106101ad57fe5b0154604051808381526020018281526020019250505060405180910390a1565b602a60006001606481106101dd57fe5b018190555056fea2646970667358221220a98485a100594465b2a199bb245f6d370e93e9ccc196010d3fd5eef924b621fd64736f6c63430007030033
gas 2000000
build

block_build b02
parent b01
transactions tx02
gasLimit 6800000
build

block_connect b02
assert_best b02

# Init SStoreClear storage
transaction_build tx03
sender acc1
nonce 2
contract tx02 # created in tx02
value 0
data 94b3f5ee
gas 6400000
build

block_build b03
parent b02
transactions tx03
gasLimit 6800000
build

block_connect b03
assert_best b03

block_build b04
parent b03
gasLimit 6800000
build

block_connect b04
assert_best b04

# callSstoreClearWithValue("56aa252dd82173789984fa164ee26ce2da9336ff")

transaction_build tx04
sender acc1
nonce 3
contract tx01 # created in tx01
value 1
data 00c6f1e600000000000000000000000056aa252dd82173789984fa164ee26ce2da9336ff
data 5b3f8140
gas 6800000
build

block_build b05
parent b04
transactions tx04
block_build b02
parent b01
transactions tx02
gasLimit 6800000
build

block_connect b05
assert_best b05
#block_connect b02
#assert_best b02

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ end

account_new acc1 20000000

# Deploy three instances of NestedCallsWithValue
# Deploy three instances of NestedCallWithValue

transaction_build tx01
sender acc1
Expand Down
Loading

0 comments on commit 7db3b4e

Please sign in to comment.