Skip to content

Commit

Permalink
feat: recover funds from SuccinctGateway (#312)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattstam authored Jan 9, 2024
1 parent de79ba5 commit f77911a
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 7 deletions.
14 changes: 12 additions & 2 deletions contracts/src/SuccinctGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ contract SuccinctGateway is ISuccinctGateway, FunctionRegistry, TimelockedUpgrad
if (msg.sender != verifierOwners[_functionId]) {
revert NotFunctionOwner(msg.sender, verifierOwners[_functionId]);
}
allowedProvers[_functionId][_prover] = false;
delete allowedProvers[_functionId][_prover];
emit ProverUpdated(_functionId, _prover, false);
}

Expand All @@ -328,7 +328,7 @@ contract SuccinctGateway is ISuccinctGateway, FunctionRegistry, TimelockedUpgrad
/// @notice Remove a default prover.
/// @param _prover The address of the prover to remove.
function removeDefaultProver(address _prover) external onlyGuardian {
allowedProvers[bytes32(0)][_prover] = false;
delete allowedProvers[bytes32(0)][_prover];
emit ProverUpdated(bytes32(0), _prover, false);
}

Expand All @@ -339,6 +339,16 @@ contract SuccinctGateway is ISuccinctGateway, FunctionRegistry, TimelockedUpgrad
feeVault = _feeVault;
}

/// @notice Recovers stuck ETH from the contract.
/// @param _to The address to send the ETH to.
/// @param _amount The wei amount of ETH to send.
function recover(address _to, uint256 _amount) external onlyGuardian {
(bool success,) = _to.call{value: _amount}("");
if (!success) {
revert RecoverFailed();
}
}

/// @dev Computes a unique identifier for a request.
/// @param _functionId The function identifier.
/// @param _inputHash The hash of the function input.
Expand Down
1 change: 1 addition & 0 deletions contracts/src/interfaces/ISuccinctGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ interface ISuccinctGatewayErrors {
error InvalidProof(address verifier, bytes32 inputHash, bytes32 outputHash, bytes proof);
error ReentrantFulfill();
error OnlyProver(bytes32 functionId, address sender);
error RecoverFailed();
}

interface ISuccinctGateway is ISuccinctGatewayEvents, ISuccinctGatewayErrors {
Expand Down
39 changes: 34 additions & 5 deletions contracts/test/SuccinctGateway.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ contract RequestTest is SuccinctGatewayTest {
bytes32 functionId = TestConsumer(consumer).FUNCTION_ID();
address callbackAddress = consumer;
bytes4 callbackSelector = TestConsumer.handleCallback.selector;
uint32 callbackGasLimit = TestConsumer(consumer).CALLBACK_GAS_LIMIT();
uint32 callbackGasLimit = DEFAULT_GAS_LIMIT;
uint256 fee = DEFAULT_FEE;
bytes memory context = abi.encode(nonce);
bytes memory output = OUTPUT;
Expand All @@ -181,7 +181,7 @@ contract RequestTest is SuccinctGatewayTest {
fee
);
vm.prank(sender);
TestConsumer(consumer).requestCallback{value: fee}();
TestConsumer(consumer).requestCallback{value: fee}(DEFAULT_GAS_LIMIT);

assertEq(prevNonce + 1, SuccinctGateway(gateway).nonce());
assertEq(TestConsumer(consumer).handledRequests(0), false);
Expand Down Expand Up @@ -219,7 +219,7 @@ contract RequestTest is SuccinctGatewayTest {
bytes32 functionId = TestConsumer(consumer).FUNCTION_ID();
address callbackAddress = consumer;
bytes4 callbackSelector = TestConsumer.handleCallback.selector;
uint32 callbackGasLimit = TestConsumer(consumer).CALLBACK_GAS_LIMIT();
uint32 callbackGasLimit = DEFAULT_GAS_LIMIT;
uint256 fee = DEFAULT_FEE;
bytes memory context = abi.encode(nonce);
bytes memory output = OUTPUT;
Expand All @@ -238,7 +238,7 @@ contract RequestTest is SuccinctGatewayTest {
fee
);
vm.prank(sender);
TestConsumer(consumer).requestCallback{value: fee}();
TestConsumer(consumer).requestCallback{value: fee}(callbackGasLimit);

assertEq(prevNonce + 1, SuccinctGateway(gateway).nonce());
assertEq(TestConsumer(consumer).handledRequests(0), false);
Expand Down Expand Up @@ -366,6 +366,12 @@ contract RequestTest is SuccinctGatewayTest {
);

assertEq(TestConsumer(consumer).handledRequests(0), true);

// Recover ETH
vm.prank(guardian);
SuccinctGateway(gateway).recover(guardian, fee);

assertEq(guardian.balance, fee);
}

function test_Callback_WhenCallbackGasLimitTooLow() public {
Expand Down Expand Up @@ -859,7 +865,7 @@ contract FunctionRegistryTest is

function test_RevertDeployAndRegisterFunction_WhenAlreadyRegistered() public {
// Deploy verifier and register function
(bytes32 functionId1,) = IFunctionRegistry(gateway).deployAndRegisterFunction(
IFunctionRegistry(gateway).deployAndRegisterFunction(
owner, type(TestFunctionVerifier1).creationCode, "test-verifier1"
);

Expand Down Expand Up @@ -1139,3 +1145,26 @@ contract SetFeeVaultTest is SuccinctGatewayTest {
SuccinctGateway(gateway).setFeeVault(newFeeVault);
}
}

contract RecoverTest is SuccinctGatewayTest {
function test_Recover() public {
uint256 fee = DEFAULT_FEE;
vm.deal(gateway, fee);

// Recover ETH
vm.prank(guardian);
SuccinctGateway(gateway).recover(guardian, fee);

assertEq(guardian.balance, fee);
}

function test_RevertRecover_WhenNotGuardian() public {
uint256 fee = DEFAULT_FEE;
vm.deal(gateway, fee);

// Recover ETH
vm.expectRevert(abi.encodeWithSignature("OnlyGuardian(address)", sender));
vm.prank(sender);
SuccinctGateway(gateway).recover(guardian, fee);
}
}

0 comments on commit f77911a

Please sign in to comment.