-
Notifications
You must be signed in to change notification settings - Fork 9
Remote GSM #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
miguelmtzinf
merged 18 commits into
aave-dao:feat/remote-gsm-TL
from
TokenLogic-com-au:remote-gsm
Aug 27, 2025
Merged
Remote GSM #1
Changes from 2 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
f7af8a0
feat: initial commit
efecarranza 79a723a
feat: finish tests
efecarranza 361c97a
fix: safecast overflow
efecarranza 6032a44
feat: overflow tests
efecarranza d064534
feat: add entity checks and delete usage
efecarranza 411edf8
fix: update test
efecarranza c172c2a
feat: add limit check on remove entity
efecarranza ffcb79b
chore: remove unnecesarry check
efecarranza 6ea6b04
chore: remove deletion
efecarranza 8d895f3
feat: add audit
efecarranza 9165f36
chore: run lint
efecarranza dc448ce
for PR
nisnislevi 6a193c5
Merge pull request #1 from Certora/certora-squashed
efecarranza 171a3b2
chore: lint certora
efecarranza edc2a14
Merge remote-tracking branch 'tl/main' into remote-gsm
efecarranza 6102ad8
chore: run ci without if
efecarranza 0987c6d
chore: add all certora ci
efecarranza fe9a3d5
chore: explicit certora key
efecarranza File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.10; | ||
|
|
||
| import {IERC20} from 'aave-v3-origin/contracts/dependencies/openzeppelin/contracts/IERC20.sol'; | ||
| import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol'; | ||
| import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; | ||
| import {VersionedInitializable} from 'aave-v3-origin/contracts/misc/aave-upgradeability/VersionedInitializable.sol'; | ||
| import {IGhoReserve} from 'src/contracts/facilitators/gsm/interfaces/IGhoReserve.sol'; | ||
|
|
||
| /** | ||
| * @title GhoReserve | ||
| * @author Aave/TokenLogic | ||
| * @notice It allows approved entities to withdraw and return GHO funds, with a defined maximum withdrawal capacity per entity. | ||
| * @dev To be covered by a proxy contract. | ||
| */ | ||
| contract GhoReserve is Ownable, VersionedInitializable, IGhoReserve { | ||
| using EnumerableSet for EnumerableSet.AddressSet; | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| address public immutable GHO_TOKEN; | ||
|
|
||
| /// Map of entities and their assigned capacity and amount of GHO used | ||
| mapping(address => GhoUsage) private _ghoUsage; | ||
|
|
||
| /// Set of entities with a GHO limit available | ||
| EnumerableSet.AddressSet private _entities; | ||
|
|
||
| /** | ||
| * @dev Constructor | ||
| * @param ghoAddress The address of the GHO token on the remote chain | ||
| */ | ||
| constructor(address ghoAddress) Ownable(msg.sender) { | ||
| require(ghoAddress != address(0), 'ZERO_ADDRESS_NOT_VALID'); | ||
| GHO_TOKEN = ghoAddress; | ||
| } | ||
|
|
||
| /** | ||
| * @dev Initializer | ||
| * @param newOwner The address of the new owner | ||
| */ | ||
| function initialize(address newOwner) external initializer { | ||
| require(newOwner != address(0), 'ZERO_ADDRESS_NOT_VALID'); | ||
| _transferOwnership(newOwner); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function use(uint256 amount) external { | ||
| GhoUsage storage entity = _ghoUsage[msg.sender]; | ||
| require(entity.limit >= entity.used + amount, 'LIMIT_EXCEEDED'); | ||
|
|
||
| entity.used += uint128(amount); | ||
| IERC20(GHO_TOKEN).transfer(msg.sender, amount); | ||
| emit GhoUsed(msg.sender, amount); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function restore(uint256 amount) external { | ||
| _ghoUsage[msg.sender].used -= uint128(amount); | ||
| IERC20(GHO_TOKEN).transferFrom(msg.sender, address(this), amount); | ||
| emit GhoRestored(msg.sender, amount); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function transfer(address to, uint256 amount) external onlyOwner { | ||
| IERC20(GHO_TOKEN).transfer(to, amount); | ||
| emit GhoTransferred(to, amount); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function addEntity(address entity) external onlyOwner { | ||
| require(_entities.add(entity), 'ENTITY_ALREADY_EXISTS'); | ||
| emit EntityAdded(entity); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function removeEntity(address entity) external onlyOwner { | ||
| require(_ghoUsage[entity].used == 0, 'ENTITY_GHO_USED_NOT_ZERO'); | ||
| require(_entities.remove(entity), 'ENTITY_NOT_REMOVED'); | ||
|
|
||
| emit EntityRemoved(entity); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function setLimit(address entity, uint256 limit) external onlyOwner { | ||
| require(_entities.contains(entity), 'ENTITY_DOES_NOT_EXIST'); | ||
| _ghoUsage[entity].limit = uint128(limit); | ||
miguelmtzinf marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| emit GhoLimitUpdated(entity, limit); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function getEntities() external view returns (address[] memory) { | ||
| return _entities.values(); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function getUsed(address entity) external view returns (uint256) { | ||
| return _ghoUsage[entity].used; | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function getUsage(address entity) external view returns (uint256, uint256) { | ||
| GhoUsage memory usage = _ghoUsage[entity]; | ||
| return (usage.limit, usage.used); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function getLimit(address entity) external view returns (uint256) { | ||
| return _ghoUsage[entity].limit; | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function isEntity(address entity) external view returns (bool) { | ||
| return _entities.contains(entity); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function totalEntities() external view returns (uint256) { | ||
| return _entities.length(); | ||
| } | ||
|
|
||
| /// @inheritdoc IGhoReserve | ||
| function GHO_REMOTE_RESERVE_REVISION() public pure virtual override returns (uint256) { | ||
| return 1; | ||
| } | ||
|
|
||
| /// @inheritdoc VersionedInitializable | ||
| function getRevision() internal pure virtual override returns (uint256) { | ||
| return GHO_REMOTE_RESERVE_REVISION(); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.