When building Gatekeep we didn’t ever want to inadvertently open additional security risks for the user. A wallet or contract needs approval to transfer an asset and we needed to trigger a transfer in case of theft, but how?
This is where Gatekeeps “Brink” contract steps into play. Brink is deployed through the dashboard and owned by the users “safe” wallet. The contracts intercept functions can only transfer the asset to the safe address that only the user can set.
We never have access to move the asset as we wish or edit variables in the contract. Only two parties can trigger an intercept function, the users wallet that deployed the contract or Gatekeeps “Guard” contract.
Brinks Code
contract GatekeepBrink is Ownable, AccessControl {
using SafeERC20 for IERC20;
address public userAddress;
address public safeAddress;
bytes32 public constant GUARD_ROLE = keccak256("GUARD_ROLE");
constructor() {
_grantRole(GUARD_ROLE, 0xb445693Dc0e164A248e452baec432FAeaDc68866);
_grantRole(GUARD_ROLE, msg.sender);
userAddress = msg.sender;
safeAddress = msg.sender;
}
function setUserAddress(address userAddress_ ) external onlyOwner {
// Set wallet address to be actively monitored.
require(userAddress_ != address(0), "Invalid address");
userAddress = userAddress_;
}
function setSafeAddress(address safeAddress_ ) external onlyOwner {
// Set address ( cold wallet recommended ) that will act as a vault. Assets will be transferred here.
require(safeAddress_ != address(0), "Invalid address");
safeAddress = safeAddress_;
}
function viewUserAddress() external view returns(address) {
return userAddress;
}
function viewSafeAddress() external view returns(address) {
return safeAddress;
}
function intercept721(uint256 _tokenId, address _contractAddress) external onlyRole(GUARD_ROLE) {
require(_contractAddress != address(0), "Invalid address");
// Intercept ERC721 asset transfer
ERC721(_contractAddress).safeTransferFrom(userAddress, safeAddress, _tokenId);
}
function intercept1155(uint256 _tokenId, address _contractAddress) external onlyRole(GUARD_ROLE) {
require(_contractAddress != address(0), "Invalid address");
// Intercept ERC1155 asset transfer
ERC1155 token1155 = ERC1155(_contractAddress);
bytes memory data = "\x01\x02\x03";
uint256 totalBalance1155 = token1155.balanceOf(userAddress, _tokenId);
token1155.safeTransferFrom(userAddress, safeAddress, _tokenId, totalBalance1155, data);
}
function intercept20(address _contractAddress) external onlyRole(GUARD_ROLE) {
require(_contractAddress != address(0), "Invalid address");
// Intercept ERC20 asset transfer
IERC20 token20 = IERC20(_contractAddress);
uint256 totalBalance20 = token20.balanceOf(userAddress);
token20.safeTransferFrom(userAddress, safeAddress, totalBalance20);
}
}