Skip to content

Commit 7589d43

Browse files
committed
Problem: missing internal tx when debug trace tx
1 parent 76bf49e commit 7589d43

File tree

6 files changed

+251
-0
lines changed

6 files changed

+251
-0
lines changed

tests/integration_tests/expected_constants.py

Lines changed: 82 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5+
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
6+
import "./BonusMultiplier.sol";
7+
8+
contract BonusDistributor {
9+
using SafeERC20 for ERC20;
10+
11+
ERC20 public bonusToken;
12+
address public bonusMultiplier;
13+
14+
constructor(address _bonusToken) {
15+
bonusToken = ERC20(_bonusToken);
16+
}
17+
18+
function setBonusMultiplier(address _bonusMultiplier) public {
19+
bonusMultiplier = _bonusMultiplier;
20+
}
21+
22+
function distributeBonusWithEther(address recipient, uint256 amount, uint256 etherValue) public {
23+
require(address(this).balance >= etherValue, "Insufficient Ether in distributor");
24+
uint256 bonusAmount = amount / 10;
25+
26+
if (bonusMultiplier != address(0)) {
27+
payable(bonusMultiplier).transfer(etherValue);
28+
BonusMultiplier(payable(bonusMultiplier)).distributeMultipliedBonusWithEther(recipient, bonusAmount, etherValue);
29+
} else {
30+
bonusToken.safeTransfer(recipient, bonusAmount);
31+
}
32+
}
33+
34+
receive() external payable {}
35+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5+
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
6+
7+
contract BonusMultiplier {
8+
using SafeERC20 for ERC20;
9+
10+
ERC20 public bonusToken;
11+
uint256 public multiplier;
12+
13+
constructor(address _bonusToken) {
14+
bonusToken = ERC20(_bonusToken);
15+
multiplier = 2;
16+
}
17+
18+
function setMultiplier(uint256 _multiplier) public {
19+
multiplier = _multiplier;
20+
}
21+
22+
function distributeMultipliedBonusWithEther(address recipient, uint256 amount, uint256 etherValue) public {
23+
require(address(this).balance >= etherValue, "Insufficient Ether in multiplier");
24+
bonusToken.safeTransfer(recipient, amount * multiplier);
25+
payable(recipient).transfer(etherValue);
26+
}
27+
28+
receive() external payable {}
29+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5+
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
6+
import "./BonusDistributor.sol";
7+
8+
contract TokenDistributor {
9+
using SafeERC20 for ERC20;
10+
11+
ERC20 public token;
12+
address public bonusDistributor;
13+
14+
constructor(address _token) {
15+
token = ERC20(_token);
16+
}
17+
18+
function setBonusDistributor(address _bonusDistributor) public {
19+
bonusDistributor = _bonusDistributor;
20+
}
21+
22+
function distributeTokens(address[] memory recipients, uint256[] memory amounts) public payable {
23+
require(recipients.length == amounts.length, "Recipients and amounts arrays must be the same length");
24+
25+
for (uint256 i = 0; i < recipients.length; i++) {
26+
token.safeTransfer(recipients[i], amounts[i]);
27+
if (bonusDistributor != address(0)) {
28+
payable(bonusDistributor).transfer(msg.value);
29+
BonusDistributor(payable(bonusDistributor)).distributeBonusWithEther(recipients[i], amounts[i], msg.value);
30+
}
31+
}
32+
}
33+
}

tests/integration_tests/test_tracers.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
EXPECTED_DEFAULT_GASCAP,
1313
EXPECTED_JS_TRACERS,
1414
EXPECTED_STRUCT_TRACER,
15+
EXPECTED_TRACE_INTERNAL_TX,
1516
)
1617
from .utils import (
1718
ADDRS,
@@ -243,6 +244,74 @@ def wait_balance():
243244
assert "insufficient funds" not in res, res
244245

245246

247+
def test_trace_internal_tx(ethermint):
248+
method = "debug_traceTransaction"
249+
tracer = {"tracer": "callTracer"}
250+
receiver = "0x0F0cb39319129BA867227e5Aae1abe9e7dd5f861"
251+
acc = derive_new_account(12)
252+
w3 = ethermint.w3
253+
fund_acc(w3, acc, fund=100000000000000000000)
254+
sender = acc.address
255+
erc20, _ = deploy_contract(w3, CONTRACTS["TestERC20A"], key=acc.key)
256+
bonus_token, _ = deploy_contract(w3, CONTRACTS["TestERC20A"], key=acc.key)
257+
token_distributor, _ = deploy_contract(
258+
w3, CONTRACTS["TokenDistributor"], (erc20.address,), key=acc.key
259+
)
260+
bonus_distributor, _ = deploy_contract(
261+
w3, CONTRACTS["BonusDistributor"], (bonus_token.address,), key=acc.key
262+
)
263+
bonus_multiplier, _ = deploy_contract(
264+
w3, CONTRACTS["BonusMultiplier"], (bonus_token.address,), key=acc.key
265+
)
266+
data = {"from": sender}
267+
tx = token_distributor.functions.setBonusDistributor(
268+
bonus_distributor.address
269+
).build_transaction(data)
270+
receipt = send_transaction(w3, tx, acc.key)
271+
assert receipt.status == 1
272+
tx = bonus_distributor.functions.setBonusMultiplier(
273+
bonus_multiplier.address
274+
).build_transaction(data)
275+
receipt = send_transaction(w3, tx, acc.key)
276+
assert receipt.status == 1
277+
278+
token_amt = 100
279+
tx = erc20.functions.transfer(
280+
token_distributor.address, token_amt
281+
).build_transaction(data)
282+
receipt = send_transaction(w3, tx, acc.key)
283+
assert receipt.status == 1
284+
tx = bonus_token.functions.transfer(
285+
bonus_multiplier.address, token_amt
286+
).build_transaction(data)
287+
receipt = send_transaction(w3, tx, acc.key)
288+
assert receipt.status == 1
289+
balance = w3.eth.get_balance(receiver)
290+
balance_erc20 = erc20.caller.balanceOf(receiver)
291+
balance_bonus = bonus_token.caller.balanceOf(receiver)
292+
amt = 25000000000000000000
293+
tx = token_distributor.functions.distributeTokens(
294+
[receiver], [token_amt]
295+
).build_transaction(
296+
{
297+
"from": sender,
298+
"nonce": w3.eth.get_transaction_count(sender),
299+
"gas": 1705533,
300+
"gasPrice": 5001500000000,
301+
"value": amt,
302+
}
303+
)
304+
receipt = send_transaction(w3, tx, acc.key)
305+
res = w3.provider.make_request(
306+
method,
307+
[receipt["transactionHash"], tracer],
308+
)
309+
assert res["result"] == EXPECTED_TRACE_INTERNAL_TX
310+
assert w3.eth.get_balance(receiver) == balance + amt
311+
assert erc20.caller.balanceOf(receiver) == balance_erc20 + token_amt
312+
assert bonus_token.caller.balanceOf(receiver) == balance_bonus + token_amt * 0.2
313+
314+
246315
def test_tracecall_insufficient_funds(ethermint, geth):
247316
method = "debug_traceCall"
248317
acc = derive_random_account()

tests/integration_tests/utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@
4646
"TestBlockTxProperties": "TestBlockTxProperties.sol",
4747
"FeeCollector": "FeeCollector.sol",
4848
"SelfDestruct": "SelfDestruct.sol",
49+
"TokenDistributor": "TokenDistributor.sol",
50+
"BonusDistributor": "BonusDistributor.sol",
51+
"BonusMultiplier": "BonusMultiplier.sol"
4952
}
5053

5154

0 commit comments

Comments
 (0)