-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathXStaker.t.sol
125 lines (109 loc) · 3.85 KB
/
XStaker.t.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;
import {XStaker} from "src/XStaker.sol";
import {XStakeController} from "src/XStakeController.sol";
import {TestToken} from "./utils/TestToken.sol";
import {MockPortal} from "omni/core/test/utils/MockPortal.sol";
import {ConfLevel} from "omni/core/src/libraries/ConfLevel.sol";
import {GasLimits} from "src/GasLimits.sol";
import {Test} from "forge-std/Test.sol";
/**
* @title XStaker_Test
* @notice Test suite for XStaker
*/
contract XStaker_Test is Test {
TestToken token;
MockPortal portal;
XStaker staker;
address controller;
function setUp() public {
controller = makeAddr("controller");
token = new TestToken();
portal = new MockPortal();
staker = new XStaker(address(portal), address(controller), address(token));
}
/**
* @notice Test XStaker.stake
*/
function test_stake() public {
address user = makeAddr("user");
uint256 balance = 100 ether;
uint256 amount = 10 ether;
uint256 fee = staker.stakeFee(amount);
// give user some tokens
token.mint(user, balance);
// approve the xstaker to spend them
vm.prank(user);
token.approve(address(staker), balance);
// requires fee
vm.expectRevert("XApp: insufficient funds");
vm.prank(user);
staker.stake(amount, ConfLevel.Finalized);
// charges fee to user
vm.deal(address(staker), 10 ether); // give staker some ether, so it ~could~ cover fee
vm.expectRevert("XStaker: insufficient fee"); // but it doesn't
vm.prank(user);
staker.stake(amount, ConfLevel.Finalized);
// stake, expect xcall to controller
vm.expectCall(
address(portal),
abi.encodeCall(
MockPortal.xcall,
(
portal.omniChainId(),
ConfLevel.Finalized,
address(controller),
abi.encodeCall(XStakeController.recordStake, (user, amount)),
GasLimits.RecordStake
)
)
);
vm.prank(user);
vm.deal(user, fee);
staker.stake{value: fee}(amount, ConfLevel.Finalized);
// check balances
assertEq(token.balanceOf(address(staker)), amount);
assertEq(token.balanceOf(user), balance - amount);
}
/**
* @notice Test XStaker.withdraw
*/
function test_withdraw() public {
address user = makeAddr("user");
uint256 amount = 10 ether;
uint64 omniChainId = portal.omniChainId();
token.mint(address(staker), amount);
// only xcall
vm.expectRevert("XStaker: only xcall");
staker.withdraw(user, amount);
// only omni
vm.expectRevert("XStaker: only omni");
portal.mockXCall({
sourceChainId: 1234, // not omni chain id
sender: address(controller),
to: address(staker),
data: abi.encodeCall(XStaker.withdraw, (user, amount)),
gasLimit: GasLimits.Withdraw
});
// only controller
vm.expectRevert("XStaker: only controller");
portal.mockXCall({
sourceChainId: omniChainId,
sender: address(1234), // not controller
to: address(staker),
data: abi.encodeCall(XStaker.withdraw, (user, amount)),
gasLimit: GasLimits.Withdraw
});
// withdraw
portal.mockXCall({
sourceChainId: portal.omniChainId(),
sender: address(controller),
to: address(staker),
data: abi.encodeCall(XStaker.withdraw, (user, amount)),
gasLimit: GasLimits.Withdraw
});
// assert balances
assertEq(token.balanceOf(address(staker)), 0);
assertEq(token.balanceOf(user), amount);
}
}