Skip to content

Commit 04b62ed

Browse files
coderbradleeCoderZhi
authored andcommitted
Add unit test for cashier.sol iotexproject#1019 (iotexproject#1032)
1 parent bc12cc7 commit 04b62ed

File tree

4 files changed

+225
-0
lines changed

4 files changed

+225
-0
lines changed

action/protocol/execution/protocol_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -674,9 +674,14 @@ func TestProtocol_Handle(t *testing.T) {
674674
t.Run("Multisend", func(t *testing.T) {
675675
NewSmartContractTest(t, "testdata/multisend.json")
676676
})
677+
// reentry
677678
t.Run("reentry-attack", func(t *testing.T) {
678679
NewSmartContractTest(t, "testdata/reentry-attack.json")
679680
})
681+
// cashier
682+
t.Run("cashier", func(t *testing.T) {
683+
NewSmartContractTest(t, "testdata/cashier.json")
684+
})
680685
}
681686

682687
func TestProtocol_Validate(t *testing.T) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
pragma solidity ^0.4.19;
2+
3+
4+
/**
5+
* @title Ownable
6+
* @dev The Ownable contract has an owner address, and provides basic authorization control
7+
* functions, this simplifies the implementation of "user permissions".
8+
*/
9+
contract Ownable {
10+
address public owner;
11+
12+
13+
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
14+
15+
16+
/**
17+
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
18+
* account.
19+
*/
20+
function Ownable() public {
21+
owner = msg.sender;
22+
}
23+
24+
/**
25+
* @dev Throws if called by any account other than the owner.
26+
*/
27+
modifier onlyOwner() {
28+
require(msg.sender == owner);
29+
_;
30+
}
31+
32+
/**
33+
* @dev Allows the current owner to transfer control of the contract to a newOwner.
34+
* @param newOwner The address to transfer ownership to.
35+
*/
36+
function transferOwnership(address newOwner) public onlyOwner {
37+
require(newOwner != address(0));
38+
OwnershipTransferred(owner, newOwner);
39+
owner = newOwner;
40+
}
41+
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
{
2+
"initBalances": [{
3+
"account": "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms",
4+
"rawBalance": "1000000000000000000000000000"
5+
}],
6+
"deployments": [{
7+
"rawByteCode": "608060405234801561001057600080fd5b50604051608080610791833981016040908152815160208301519183015160609093015160008054600160a060020a03191633179055909290600160a060020a038416151561005e57600080fd5b6000821161006b57600080fd5b8181101561007857600080fd5b60018054600160a060020a031916600160a060020a039590951694909417909355600291909155600355600455623d09006005556106d6806100bb6000396000f3006080604052600436106100fb5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663046f7da28114610105578063186f03541461011a5780632e1a7d4d1461014b57806345f0a44f14610163578063490ae2101461018d5780634fe47f70146101a55780635db0cb94146101bd5780635f48f393146101de57806367a52793146101f35780638456cb5914610208578063897b06371461021d5780638da5cb5b146102355780639b2cb5d81461024a578063c0abda2a1461025f578063d0e30db0146100fb578063ee7d72b414610277578063f2fde38b1461028f578063f68016b7146102b0575b6101036102c5565b005b34801561011157600080fd5b506101036103f0565b34801561012657600080fd5b5061012f610424565b60408051600160a060020a039092168252519081900360200190f35b34801561015757600080fd5b50610103600435610433565b34801561016f57600080fd5b5061017b600435610489565b60408051918252519081900360200190f35b34801561019957600080fd5b506101036004356104a8565b3480156101b157600080fd5b506101036004356104c4565b3480156101c957600080fd5b50610103600160a060020a03600435166104ef565b3480156101ea57600080fd5b5061017b61054a565b3480156101ff57600080fd5b5061017b610550565b34801561021457600080fd5b50610103610556565b34801561022957600080fd5b5061010360043561058c565b34801561024157600080fd5b5061012f6105b7565b34801561025657600080fd5b5061017b6105c6565b34801561026b57600080fd5b5061012f6004356105cc565b34801561028357600080fd5b506101036004356105f4565b34801561029b57600080fd5b50610103600160a060020a0360043516610610565b3480156102bc57600080fd5b5061017b6106a4565b60085460009060ff16156102d857600080fd5b600254600354013410156102eb57600080fd5b60025434039050600454811115151561030357600080fd5b600154600554604051600160a060020a039092169183906000818181858888f19350505050156103ed576006805460018181019092557ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f01805473ffffffffffffffffffffffffffffffffffffffff1916339081179091556007805492830181556000527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c68890910182905560025460408051848152602081019290925280517fb54144b2711919f9fb59c30ec3b593b154784e26488806a6ddb320c41b5c1c939281900390910190a25b50565b600054600160a060020a0316331461040757600080fd5b60085460ff16151561041857600080fd5b6008805460ff19169055565b600154600160a060020a031681565b600054600160a060020a0316331461044a57600080fd5b303181111561045857600080fd5b604051339082156108fc029083906000818181858888f19350505050158015610485573d6000803e3d6000fd5b5050565b600780548290811061049757fe5b600091825260209091200154905081565b600054600160a060020a031633146104bf57600080fd5b600255565b600054600160a060020a031633146104db57600080fd5b6003548110156104ea57600080fd5b600455565b600054600160a060020a0316331461050657600080fd5b600160a060020a038116151561051b57600080fd5b6001805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60045481565b60025481565b600054600160a060020a0316331461056d57600080fd5b60085460ff161561057d57600080fd5b6008805460ff19166001179055565b600054600160a060020a031633146105a357600080fd5b6004548111156105b257600080fd5b600355565b600054600160a060020a031681565b60035481565b60068054829081106105da57fe5b600091825260209091200154600160a060020a0316905081565b600054600160a060020a0316331461060b57600080fd5b600555565b600054600160a060020a0316331461062757600080fd5b600160a060020a038116151561063c57600080fd5b60008054604051600160a060020a03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600554815600a165627a7a72305820d8278a1efc7155cd5660666a40251a6011e1387cb8adbb4bfdcc17082890c1c00029000000000000000000000000cecc938840c5ae89373a681a5f2e0f244152e91b000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000186a000000000000000000000000000000000000000000000000000000000000f4240",
8+
"rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
9+
"rawAmount": "0",
10+
"rawGasLimit": 5000000,
11+
"rawGasPrice": "0",
12+
"expectedBalances": [],
13+
"comment": "deploy cashier contract"
14+
}],
15+
"executions": [{
16+
"rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
17+
"rawByteCode": "d0e30db0",
18+
"rawAmount": "110000",
19+
"rawGasLimit": 1000000,
20+
"rawGasPrice": "0",
21+
"expectedBalances": [{
22+
"account": "io1emxf8zzqckhgjde6dqd97ts0y3q496gm3fdrl6",
23+
"rawBalance": "100000"
24+
},{
25+
"account": "",
26+
"rawBalance": "10000"
27+
}],
28+
"expectedLogs": [{}],
29+
"comment": "call deposit"
30+
},{
31+
"rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
32+
"rawByteCode": "d0e30db0",
33+
"rawAmount": "90000",
34+
"rawGasLimit": 1000000,
35+
"rawGasPrice": "0",
36+
"failed": true,
37+
"expectedBalances": [{
38+
"account": "io1emxf8zzqckhgjde6dqd97ts0y3q496gm3fdrl6",
39+
"rawBalance": "100000"
40+
},{
41+
"account": "",
42+
"rawBalance": "10000"
43+
}],
44+
"expectedLogs": [],
45+
"comment": "call deposit msg.value < minAmount + depositFee"
46+
},{
47+
"rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
48+
"rawByteCode": "d0e30db0",
49+
"rawAmount": "1020000",
50+
"rawGasLimit": 1000000,
51+
"rawGasPrice": "0",
52+
"failed": true,
53+
"expectedBalances": [{
54+
"account": "io1emxf8zzqckhgjde6dqd97ts0y3q496gm3fdrl6",
55+
"rawBalance": "100000"
56+
},{
57+
"account": "",
58+
"rawBalance": "10000"
59+
}],
60+
"expectedLogs": [],
61+
"comment": "call deposit msg.value>maxAmount + depositFee"
62+
},{
63+
"rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
64+
"rawByteCode": "2e1a7d4d0000000000000000000000000000000000000000000000000000000000000064",
65+
"rawAmount": "0",
66+
"rawGasLimit": 1000000,
67+
"rawGasPrice": "0",
68+
"expectedBalances": [{
69+
"account": "io1emxf8zzqckhgjde6dqd97ts0y3q496gm3fdrl6",
70+
"rawBalance": "100000"
71+
},{
72+
"account": "",
73+
"rawBalance": "9900"
74+
}],
75+
"expectedLogs": [],
76+
"comment": "call withdraw 100"
77+
},{
78+
"rawPrivateKey": "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
79+
"rawByteCode": "2e1a7d4d0000000000000000000000000000000000000000000000000000000000004E20",
80+
"rawAmount": "0",
81+
"rawGasLimit": 1000000,
82+
"rawGasPrice": "0",
83+
"failed": true,
84+
"expectedBalances": [{
85+
"account": "io1emxf8zzqckhgjde6dqd97ts0y3q496gm3fdrl6",
86+
"rawBalance": "100000"
87+
},{
88+
"account": "",
89+
"rawBalance": "9900"
90+
}],
91+
"expectedLogs": [],
92+
"comment": "call withdraw 20000,expect failed"
93+
}]
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
pragma solidity ^0.4.24;
2+
3+
import "./Ownable.sol";
4+
5+
contract Cashier is Ownable {
6+
address public safe;
7+
uint256 public depositFee;
8+
uint256 public minAmount;
9+
uint256 public maxAmount;
10+
uint256 public gasLimit;
11+
address[] public customers;
12+
uint256[] public amounts;
13+
bool paused;
14+
15+
event Receipt(address indexed customer, uint256 amount, uint256 fee);
16+
17+
function Cashier(address _safe, uint256 _fee, uint256 _minAmount, uint256 _maxAmount) public {
18+
require(_safe != address(0));
19+
require(_minAmount > 0);
20+
require(_maxAmount >= _minAmount);
21+
safe = _safe;
22+
depositFee = _fee;
23+
minAmount = _minAmount;
24+
maxAmount = _maxAmount;
25+
gasLimit = 4000000;
26+
}
27+
28+
function () external payable {
29+
deposit();
30+
}
31+
32+
function deposit() public payable {
33+
require(!paused);
34+
require(msg.value >= minAmount + depositFee);
35+
uint256 amount = msg.value - depositFee;
36+
require(amount <= maxAmount);
37+
38+
if (safe.call.value(amount).gas(gasLimit)()) {
39+
customers.push(msg.sender);
40+
amounts.push(amount);
41+
42+
emit Receipt(msg.sender, amount, depositFee);
43+
}
44+
}
45+
46+
function withdraw(uint256 amount) external onlyOwner {
47+
require(address(this).balance >= amount);
48+
msg.sender.transfer(amount);
49+
}
50+
51+
function setSafe(address _safe) external onlyOwner {
52+
require(_safe != address(0));
53+
safe = _safe;
54+
}
55+
56+
function setMinAmount(uint256 _minAmount) external onlyOwner {
57+
require(maxAmount >= _minAmount);
58+
minAmount = _minAmount;
59+
}
60+
61+
function setMaxAmount(uint256 _maxAmount) external onlyOwner {
62+
require(_maxAmount >= minAmount);
63+
maxAmount = _maxAmount;
64+
}
65+
66+
function setDepositFee(uint256 _fee) external onlyOwner {
67+
depositFee = _fee;
68+
}
69+
70+
function setGasLimit(uint256 _gasLimit) external onlyOwner {
71+
gasLimit = _gasLimit;
72+
}
73+
74+
function pause() external onlyOwner {
75+
require(!paused);
76+
paused = true;
77+
}
78+
79+
function resume() external onlyOwner {
80+
require(paused);
81+
paused = false;
82+
}
83+
84+
}

0 commit comments

Comments
 (0)