Skip to content

Commit f26b522

Browse files
authored
Minor router logic update and tests (#261)
* updated router behavior to return created vault back to the user after creation * router tests * fixed unstake/restake parameter ordering
1 parent 04261ee commit f26b522

File tree

8 files changed

+299
-39
lines changed

8 files changed

+299
-39
lines changed

contracts/Mock/MockERC20.sol

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,37 @@ pragma solidity 0.7.6;
44
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
55
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
66

7-
contract MockERC20 is ERC20 {
7+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
8+
import "@openzeppelin/contracts/drafts/IERC20Permit.sol";
9+
10+
contract MockERC20 is ERC20, IERC20Permit {
11+
mapping(address => uint256) public override nonces;
12+
813
constructor(address recipient, uint256 amount) ERC20("MockERC20", "MockERC20") {
914
ERC20._mint(recipient, amount);
1015
}
16+
17+
// Hard-coded DOMAIN_SEPARATOR for testing purposes only.
18+
// In a real implementation, this would be derived from EIP-712 parameters.
19+
function DOMAIN_SEPARATOR() external pure override returns (bytes32) {
20+
return 0x00;
21+
}
22+
23+
function permit(
24+
address owner,
25+
address spender,
26+
uint256 value,
27+
uint256, // deadline - ignored in mock
28+
uint8, // v - ignored in mock
29+
bytes32, // r - ignored in mock
30+
bytes32 // s - ignored in mock
31+
) external override {
32+
// For testing, ignore signature checks and deadline.
33+
// Simply set allowance directly.
34+
_approve(owner, spender, value);
35+
// Increment nonce as if a successful permit was used.
36+
nonces[owner]++;
37+
}
1138
}
1239

1340
contract MockBAL is ERC20 {

contracts/Mock/MockGeyser.sol

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,22 @@ contract MockGeyser {
2727
});
2828
}
2929

30-
event LogStaked(address vault, uint256 amount, bytes permission);
30+
event Staked(address vault, uint256 amount, bytes permission);
31+
event UnstakedAndClaimed(address vault, uint256 amount, bytes permission);
3132

3233
function stake(
3334
address vault,
3435
uint256 amount,
3536
bytes calldata permission
3637
) external {
37-
emit LogStaked(vault, amount, permission);
38+
emit Staked(vault, amount, permission);
39+
}
40+
41+
function unstakeAndClaim(
42+
address vault,
43+
uint256 amount,
44+
bytes calldata permission
45+
) external {
46+
emit UnstakedAndClaimed(vault, amount, permission);
3847
}
3948
}

contracts/Mock/MockVaultFactory.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ contract MockVaultFactory is ERC721("MockVaultFactory", "MVF") {
1717
) external returns (address) {
1818
uint256 vaultId = nextVaultId;
1919
nextVaultId++;
20-
_mint(msg.sender, vaultId);
20+
ERC721._safeMint(msg.sender, vaultId);
2121
return address(uint160(vaultId));
2222
}
2323
}

contracts/Router/CharmGeyserRouter.sol

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,7 @@ contract CharmGeyserRouter is GeyserRouter {
7575
bytes calldata permission,
7676
LiqCreationPayload memory d
7777
) external returns (address vault) {
78-
// create vault
79-
vault = create2Vault(vaultFactory, salt);
80-
81-
// transfer ownership
82-
IERC721(vaultFactory).safeTransferFrom(address(this), vaultOwner, uint256(vault));
83-
78+
vault = create2Vault(vaultFactory, salt, vaultOwner);
8479
// create liquidity and stake
8580
createLiqAndStake(geyser, vault, permission, d);
8681
}

contracts/Router/GeyserRouter.sol

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,15 @@ contract GeyserRouter is IERC721Receiver {
2525
return IERC721Receiver.onERC721Received.selector;
2626
}
2727

28-
function create2Vault(address vaultFactory, bytes32 salt) public returns (address vault) {
28+
function create2Vault(
29+
address vaultFactory,
30+
bytes32 salt,
31+
address vaultOwner
32+
) public returns (address vault) {
33+
// create vault
2934
vault = IFactory(vaultFactory).create2("", salt);
35+
// transfer ownership
36+
IERC721(vaultFactory).safeTransferFrom(address(this), vaultOwner, uint256(vault));
3037
}
3138

3239
function depositStake(
@@ -48,10 +55,7 @@ contract GeyserRouter is IERC721Receiver {
4855
bytes32 salt,
4956
bytes calldata permission
5057
) external returns (address vault) {
51-
// create vault
52-
vault = create2Vault(vaultFactory, salt);
53-
// transfer ownership
54-
IERC721(vaultFactory).safeTransferFrom(address(this), vaultOwner, uint256(vault));
58+
vault = create2Vault(vaultFactory, salt, vaultOwner);
5559
// transfer tokens and stake
5660
depositStake(geyser, vault, amount, permission);
5761
}
@@ -108,36 +112,29 @@ contract GeyserRouter is IERC721Receiver {
108112
IGeyser(geyser).stake(vault, permit.value, permission);
109113
}
110114

111-
struct StakeRequest {
115+
struct GeyserAction {
112116
address geyser;
113117
address vault;
114118
uint256 amount;
115119
bytes permission;
116120
}
117121

118-
function stakeMulti(StakeRequest[] calldata requests) external {
119-
for (uint256 index = 0; index < requests.length; index++) {
120-
StakeRequest calldata request = requests[index];
121-
IGeyser(request.geyser).stake(request.vault, request.amount, request.permission);
122+
function stakeMulti(GeyserAction[] calldata actions) external {
123+
for (uint256 index = 0; index < actions.length; index++) {
124+
GeyserAction calldata act = actions[index];
125+
IGeyser(act.geyser).stake(act.vault, act.amount, act.permission);
122126
}
123127
}
124128

125-
struct UnstakeRequest {
126-
address geyser;
127-
address vault;
128-
uint256 amount;
129-
bytes permission;
130-
}
131-
132-
function unstakeMulti(UnstakeRequest[] calldata requests) external {
133-
for (uint256 index = 0; index < requests.length; index++) {
134-
UnstakeRequest calldata request = requests[index];
135-
IGeyser(request.geyser).unstakeAndClaim(request.vault, request.amount, request.permission);
129+
function unstakeMulti(GeyserAction[] calldata actions) external {
130+
for (uint256 index = 0; index < actions.length; index++) {
131+
GeyserAction calldata act = actions[index];
132+
IGeyser(act.geyser).unstakeAndClaim(act.vault, act.amount, act.permission);
136133
}
137134
}
138135

139-
function unstakeAndRestake(UnstakeRequest calldata r1, StakeRequest calldata r2) external {
140-
IGeyser(r1.geyser).stake(r1.vault, r1.amount, r1.permission);
141-
IGeyser(r2.geyser).unstakeAndClaim(r2.vault, r2.amount, r2.permission);
136+
function unstakeAndRestake(GeyserAction calldata unstakeAct, GeyserAction calldata stakeAct) external {
137+
IGeyser(unstakeAct.geyser).unstakeAndClaim(unstakeAct.vault, unstakeAct.amount, unstakeAct.permission);
138+
IGeyser(stakeAct.geyser).stake(stakeAct.vault, stakeAct.amount, stakeAct.permission);
142139
}
143140
}

frontend/src/sdk/actions.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,11 @@ export const approveCreateDepositStake = async (geyserAddress: string, amount: B
129129
const token = new Contract(tokenAddress, ERC20_ABI, signer)
130130

131131
const salt = randomBytes(32)
132-
const vaultAddress = await router.callStatic.create2Vault(config.VaultFactory.address, salt)
132+
const vaultAddress = await router.callStatic.create2Vault(
133+
config.VaultFactory.address,
134+
salt,
135+
await signer.getAddress(),
136+
)
133137
const vault = new Contract(vaultAddress, config.VaultTemplate.abi, signer)
134138
const lockPermission = await signPermission('Lock', vault, signer, geyserAddress, token.address, amount, '0')
135139
const args = [geyserAddress, config.VaultFactory.address, await signer.getAddress(), amount, salt, lockPermission]
@@ -186,7 +190,11 @@ export const permitCreateDepositStake = async (geyserAddress: string, amount: Bi
186190
}
187191

188192
const salt = randomBytes(32)
189-
const vaultAddress = await router.callStatic.create2Vault(config.VaultFactory.address, salt)
193+
const vaultAddress = await router.callStatic.create2Vault(
194+
config.VaultFactory.address,
195+
salt,
196+
await signer.getAddress(),
197+
)
190198
const vault = new Contract(vaultAddress, config.VaultTemplate.address, signer)
191199

192200
const permit = await signPermitEIP2612(signer, tokenAddress, router.address, amount, deadline)

test/CharmGeyserRouter.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ describe('CharmGeyserRouter', function () {
6565
}
6666

6767
await expect(router.connect(user).createLiqAndStake(geyser.address, vault, '0x', liqPayload))
68-
.to.emit(geyser, 'LogStaked')
68+
.to.emit(geyser, 'Staked')
6969
.withArgs(vault, token0Amount.add(token1Amount), '0x')
7070

7171
// After staking, router should have transferred all tokens out
@@ -98,7 +98,7 @@ describe('CharmGeyserRouter', function () {
9898
const args = [geyser.address, vaultFactory.address, await vaultOwner.getAddress(), salt, '0x', liqPayload]
9999
const vault = await router.connect(user).callStatic.create2VaultCreateLiqAndStake(...args)
100100
await expect(router.connect(user).create2VaultCreateLiqAndStake(...args))
101-
.to.emit(geyser, 'LogStaked')
101+
.to.emit(geyser, 'Staked')
102102
.withArgs(vault, token0Amount.add(token1Amount), '0x')
103103
expect(await vaultFactory.ownerOf(1)).to.equal(await vaultOwner.getAddress())
104104
})
@@ -145,7 +145,7 @@ describe('CharmGeyserRouter', function () {
145145
}
146146

147147
await expect(router.connect(user).createLiqAndStake(geyser.address, vault, '0x', liqPayload))
148-
.to.emit(geyser, 'LogStaked')
148+
.to.emit(geyser, 'Staked')
149149
.withArgs(vault, 0, '0x')
150150
})
151151
})

0 commit comments

Comments
 (0)