Skip to content

Commit

Permalink
Minor router logic update and tests (#261)
Browse files Browse the repository at this point in the history
* updated router behavior to return created vault back to the user after creation

* router tests

* fixed unstake/restake parameter ordering
  • Loading branch information
aalavandhan authored Dec 21, 2024
1 parent 04261ee commit f26b522
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 39 deletions.
29 changes: 28 additions & 1 deletion contracts/Mock/MockERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,37 @@ pragma solidity 0.7.6;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MockERC20 is ERC20 {
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/drafts/IERC20Permit.sol";

contract MockERC20 is ERC20, IERC20Permit {
mapping(address => uint256) public override nonces;

constructor(address recipient, uint256 amount) ERC20("MockERC20", "MockERC20") {
ERC20._mint(recipient, amount);
}

// Hard-coded DOMAIN_SEPARATOR for testing purposes only.
// In a real implementation, this would be derived from EIP-712 parameters.
function DOMAIN_SEPARATOR() external pure override returns (bytes32) {
return 0x00;
}

function permit(
address owner,
address spender,
uint256 value,
uint256, // deadline - ignored in mock
uint8, // v - ignored in mock
bytes32, // r - ignored in mock
bytes32 // s - ignored in mock
) external override {
// For testing, ignore signature checks and deadline.
// Simply set allowance directly.
_approve(owner, spender, value);
// Increment nonce as if a successful permit was used.
nonces[owner]++;
}
}

contract MockBAL is ERC20 {
Expand Down
13 changes: 11 additions & 2 deletions contracts/Mock/MockGeyser.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,22 @@ contract MockGeyser {
});
}

event LogStaked(address vault, uint256 amount, bytes permission);
event Staked(address vault, uint256 amount, bytes permission);
event UnstakedAndClaimed(address vault, uint256 amount, bytes permission);

function stake(
address vault,
uint256 amount,
bytes calldata permission
) external {
emit LogStaked(vault, amount, permission);
emit Staked(vault, amount, permission);
}

function unstakeAndClaim(
address vault,
uint256 amount,
bytes calldata permission
) external {
emit UnstakedAndClaimed(vault, amount, permission);
}
}
2 changes: 1 addition & 1 deletion contracts/Mock/MockVaultFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ contract MockVaultFactory is ERC721("MockVaultFactory", "MVF") {
) external returns (address) {
uint256 vaultId = nextVaultId;
nextVaultId++;
_mint(msg.sender, vaultId);
ERC721._safeMint(msg.sender, vaultId);
return address(uint160(vaultId));
}
}
7 changes: 1 addition & 6 deletions contracts/Router/CharmGeyserRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,7 @@ contract CharmGeyserRouter is GeyserRouter {
bytes calldata permission,
LiqCreationPayload memory d
) external returns (address vault) {
// create vault
vault = create2Vault(vaultFactory, salt);

// transfer ownership
IERC721(vaultFactory).safeTransferFrom(address(this), vaultOwner, uint256(vault));

vault = create2Vault(vaultFactory, salt, vaultOwner);
// create liquidity and stake
createLiqAndStake(geyser, vault, permission, d);
}
Expand Down
45 changes: 21 additions & 24 deletions contracts/Router/GeyserRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,15 @@ contract GeyserRouter is IERC721Receiver {
return IERC721Receiver.onERC721Received.selector;
}

function create2Vault(address vaultFactory, bytes32 salt) public returns (address vault) {
function create2Vault(
address vaultFactory,
bytes32 salt,
address vaultOwner
) public returns (address vault) {
// create vault
vault = IFactory(vaultFactory).create2("", salt);
// transfer ownership
IERC721(vaultFactory).safeTransferFrom(address(this), vaultOwner, uint256(vault));
}

function depositStake(
Expand All @@ -48,10 +55,7 @@ contract GeyserRouter is IERC721Receiver {
bytes32 salt,
bytes calldata permission
) external returns (address vault) {
// create vault
vault = create2Vault(vaultFactory, salt);
// transfer ownership
IERC721(vaultFactory).safeTransferFrom(address(this), vaultOwner, uint256(vault));
vault = create2Vault(vaultFactory, salt, vaultOwner);
// transfer tokens and stake
depositStake(geyser, vault, amount, permission);
}
Expand Down Expand Up @@ -108,36 +112,29 @@ contract GeyserRouter is IERC721Receiver {
IGeyser(geyser).stake(vault, permit.value, permission);
}

struct StakeRequest {
struct GeyserAction {
address geyser;
address vault;
uint256 amount;
bytes permission;
}

function stakeMulti(StakeRequest[] calldata requests) external {
for (uint256 index = 0; index < requests.length; index++) {
StakeRequest calldata request = requests[index];
IGeyser(request.geyser).stake(request.vault, request.amount, request.permission);
function stakeMulti(GeyserAction[] calldata actions) external {
for (uint256 index = 0; index < actions.length; index++) {
GeyserAction calldata act = actions[index];
IGeyser(act.geyser).stake(act.vault, act.amount, act.permission);
}
}

struct UnstakeRequest {
address geyser;
address vault;
uint256 amount;
bytes permission;
}

function unstakeMulti(UnstakeRequest[] calldata requests) external {
for (uint256 index = 0; index < requests.length; index++) {
UnstakeRequest calldata request = requests[index];
IGeyser(request.geyser).unstakeAndClaim(request.vault, request.amount, request.permission);
function unstakeMulti(GeyserAction[] calldata actions) external {
for (uint256 index = 0; index < actions.length; index++) {
GeyserAction calldata act = actions[index];
IGeyser(act.geyser).unstakeAndClaim(act.vault, act.amount, act.permission);
}
}

function unstakeAndRestake(UnstakeRequest calldata r1, StakeRequest calldata r2) external {
IGeyser(r1.geyser).stake(r1.vault, r1.amount, r1.permission);
IGeyser(r2.geyser).unstakeAndClaim(r2.vault, r2.amount, r2.permission);
function unstakeAndRestake(GeyserAction calldata unstakeAct, GeyserAction calldata stakeAct) external {
IGeyser(unstakeAct.geyser).unstakeAndClaim(unstakeAct.vault, unstakeAct.amount, unstakeAct.permission);
IGeyser(stakeAct.geyser).stake(stakeAct.vault, stakeAct.amount, stakeAct.permission);
}
}
12 changes: 10 additions & 2 deletions frontend/src/sdk/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,11 @@ export const approveCreateDepositStake = async (geyserAddress: string, amount: B
const token = new Contract(tokenAddress, ERC20_ABI, signer)

const salt = randomBytes(32)
const vaultAddress = await router.callStatic.create2Vault(config.VaultFactory.address, salt)
const vaultAddress = await router.callStatic.create2Vault(
config.VaultFactory.address,
salt,
await signer.getAddress(),
)
const vault = new Contract(vaultAddress, config.VaultTemplate.abi, signer)
const lockPermission = await signPermission('Lock', vault, signer, geyserAddress, token.address, amount, '0')
const args = [geyserAddress, config.VaultFactory.address, await signer.getAddress(), amount, salt, lockPermission]
Expand Down Expand Up @@ -186,7 +190,11 @@ export const permitCreateDepositStake = async (geyserAddress: string, amount: Bi
}

const salt = randomBytes(32)
const vaultAddress = await router.callStatic.create2Vault(config.VaultFactory.address, salt)
const vaultAddress = await router.callStatic.create2Vault(
config.VaultFactory.address,
salt,
await signer.getAddress(),
)
const vault = new Contract(vaultAddress, config.VaultTemplate.address, signer)

const permit = await signPermitEIP2612(signer, tokenAddress, router.address, amount, deadline)
Expand Down
6 changes: 3 additions & 3 deletions test/CharmGeyserRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ describe('CharmGeyserRouter', function () {
}

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

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

await expect(router.connect(user).createLiqAndStake(geyser.address, vault, '0x', liqPayload))
.to.emit(geyser, 'LogStaked')
.to.emit(geyser, 'Staked')
.withArgs(vault, 0, '0x')
})
})
Expand Down
Loading

0 comments on commit f26b522

Please sign in to comment.