Skip to content

Commit 1f503fa

Browse files
Rebase Bridging about to be completed
1 parent 6d4e575 commit 1f503fa

File tree

11 files changed

+218
-106
lines changed

11 files changed

+218
-106
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ out/
1111
docs/
1212

1313
# Dotenv file
14-
.env
14+
.env

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
[submodule "lib/openzeppelin-contracts"]
55
path = lib/openzeppelin-contracts
66
url = https://github.com/openzeppelin/openzeppelin-contracts
7+
[submodule "lib/ccip"]
8+
path = lib/ccip
9+
url = https://github.com/smartcontractkit/ccip

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,9 @@ Incentivizing Early Adopters: This design directly rewards early users. Because
3131

3232
Handling Subsequent Deposits: If an existing user makes additional deposits at a later time, those new deposits would likely accrue interest based on the (potentially lower) global interest rate prevailing at the time of the new deposit. The exact mechanics for handling multiple deposits from the same user and their associated rates will be detailed during contract implementation.
3333

34-
Conceptual Source of Yield: While the underlying assets in the Vault could theoretically be deployed in various DeFi strategies (e.g., staking, lending, liquidity provision) to generate yield, for this initial version, the "interest" is primarily a function of the rebase mechanism itself, designed to increase token adoption by directly rewarding token holders with more tokens.
34+
Conceptual Source of Yield: While the underlying assets in the Vault could theoretically be deployed in various DeFi strategies (e.g., staking, lending, liquidity provision) to generate yield, for this initial version, the "interest" is primarily a function of the rebase mechanism itself, designed to increase token adoption by directly rewarding token holders with more tokens.
35+
36+
37+
---------------- Vulnerabilities identified --------------------------------------------
38+
1. When user deposit and amount and comes back to deposite another amount, their intial interest rate is applied instead of the recent adjusted interest rate. : this gives early adopters insane amount of benefit
39+
2. Because interest is derived by multiplying with the growth factor and the balanceOf(), it compounds rather than accumulating linearly

foundry.toml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ out = "out"
44
libs = ["lib"]
55

66
remappings = [
7-
"@openzeppelin/=lib/openzeppelin-contracts/"
7+
"@openzeppelin/=lib/openzeppelin-contracts/",
8+
'@ccip/=lib/ccip/'
89
]
10+
[fuzz]
11+
run=250
912
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
13+
14+
15+

lib/ccip

Submodule ccip added at ae80e25

remapping.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// remappings.txt
2+
@openzeppelin/=lib/openzeppelin-contracts/
3+
@ccip/=lib/ccip/

src/RebaseToken.sol

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,7 @@ contract RebaseToken is ERC20, Ownable, AccessControl {
172172
* @param _user The address of the user.
173173
* @return The growth factor, scaled by PRECISION_FACTOR. (e.g., 1.05x growth is 1.05 * 1e18)
174174
*/
175-
function _calculateUserAccumulatedInterestSinceLastUpdate(address _user)
176-
internal
177-
view
178-
returns (uint256)
179-
{
175+
function _calculateUserAccumulatedInterestSinceLastUpdate(address _user) internal view returns (uint256) {
180176
uint256 timeElapsed = block.timestamp - s_userLastTimestamp[_user];
181177
if (timeElapsed == 0 || s_userInterestRate[_user] == 0) {
182178
return PRECISION_FACTOR;
@@ -190,14 +186,8 @@ contract RebaseToken is ERC20, Ownable, AccessControl {
190186
}
191187

192188
//------------- getters, views and pure functions ---------------------------------------
193-
/**
194-
* @notice Gets the locked-in interest rate for a specific user.
195-
* @param _user The address of the user.
196-
* @return The user's specific interest rate.
197-
*/
198-
function getUserInterestRate(address _user) external view returns (uint256) {
199-
return s_userInterestRate[_user];
200-
}
189+
190+
201191

202192
/**
203193
* @notice Gets the principle balance of a user (tokens actually minted to them), excluding any accrued interest.
@@ -215,4 +205,9 @@ contract RebaseToken is ERC20, Ownable, AccessControl {
215205
function getInterestRate() public view returns (uint256) {
216206
return s_interestRate;
217207
}
208+
209+
//get user's interets rate
210+
function getUserInterestRate(address _user) external returns (uint256){
211+
return s_userInterestRate[_user];
212+
}
218213
}

src/RebaseTokenPool.sol

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
//SPDX-License-Identifier:MIT
2+
pragma solidity^0.8.24;
3+
4+
import {TokenPool} from "@ccip/contracts/src/v0.8/ccip/pools/TokenPool.sol";
5+
import {IERC20} from "@ccip/contracts/src/v0.8/vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol";
6+
import {IRebaseToken} from "./interfaces/IRebaseToken.sol"; // Adjust path if your interface is elsewhere
7+
import {Pool} from "@ccip/contracts/src/v0.8/ccip/libraries/Pool.sol"; // For CCIP structs
8+
9+
contract RebaseTokenPool is TokenPool{
10+
11+
/*** The TokenPool base constructor requires:
12+
* @_token: The address of the rebase token this pool will manage.
13+
* @
14+
* @localTokenDecimals: The decimals of the token. Here, it's hardcoded to 18.
15+
* @
16+
* @_allowlist: An array of addresses permitted to send tokens through this pool.
17+
* @
18+
* @_rnmProxy: The address of the CCIP Risk Management Network (RMN) proxy.
19+
* @
20+
* @_router: The address of the CCIP router contract.
21+
*/
22+
constructor (
23+
IERC20 _token,
24+
address[] memory _allowList,
25+
address i_rmnProxy,
26+
address _router
27+
)TokenPool(_token,_allowList,i_rmnProxy,_router){
28+
//constructor body
29+
}
30+
31+
32+
// lockorburn function to process burning upon transfering
33+
function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) external returns (Pool.LockOrBurnOutV1 memory lockOrBurnOut) {
34+
_validateLockOrBurn(lockOrBurnIn);
35+
// Decode the original sender's address
36+
address originalSender = abi.decode(lockOrBurnIn.originalSender, (address));
37+
38+
// Fetch the user's current interest rate from the rebase token
39+
uint256 userInterestRate = IRebaseToken(address(i_token)).getUserInterestRate(originalSender);
40+
// Burn the specified amount of tokens from this pool contract
41+
// CCIP transfers tokens to the pool before lockOrBurn is called
42+
IRebaseToken(address(i_token)).burn(address(this), lockOrBurnIn.amount);
43+
// Prepare the output data for CCIP
44+
lockOrBurnOut = Pool.LockOrBurnOutV1({
45+
destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector),
46+
destPoolData: abi.encode(userInterestRate) // Encode the interest rate to send cross-chain
47+
});
48+
// No explicit return statement is needed due to the named return variable
49+
}
50+
51+
// when tokens are beign receive on the chain where this RebaseTokenPool is deployed
52+
function releaseOrMint(
53+
Pool.ReleaseOrMintInV1 calldata releaseOrMintIn
54+
) external override returns (Pool.ReleaseOrMintOutV1 memory /* releaseOrMintOut */) { // Named return optional
55+
_validateReleaseOrMint(releaseOrMintIn);
56+
// Decode the user interest rate sent from the source pool
57+
uint256 userInterestRate = abi.decode(releaseOrMintIn.sourcePoolData, (uint256));
58+
59+
// The receiver address is directly available
60+
address receiver = releaseOrMintIn.receiver;
61+
// Mint tokens to the receiver, applying the propagated interest rate
62+
IRebaseToken(address(i_token)).mint(
63+
receiver,
64+
releaseOrMintIn.amount,
65+
userInterestRate // Pass the interest rate to the rebase token's mint function
66+
);
67+
return Pool.ReleaseOrMintOutV1({
68+
destinationAmount: releaseOrMintIn.amount
69+
});
70+
}
71+
72+
}

src/Vault.sol

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ contract Vault {
3030
revert Vault_NotEthSent();
3131
}
3232
// give mint
33-
i_rebaseToken.mint(msg.sender, amountToDeposite); yui
34-
33+
i_rebaseToken.mint(msg.sender, amountToDeposite);
34+
3535
emit Vault_EthDeposited(msg.sender, amountToDeposite);
3636
}
3737

@@ -40,21 +40,22 @@ contract Vault {
4040
* @param _amount The amount of RebaseTokens to redeem.
4141
* @dev Follows Checks-Effects-Interactions pattern. Uses low-level .call for ETH transfer.
4242
*/
43-
function redeem(uint256 _amount) public {
43+
function redeem(uint256 _amount) public {
4444
// burn token amount to be redeemed
4545
i_rebaseToken.burn(msg.sender, _amount);
46-
//transfer token to user
47-
(bool success,)= payable(msg.sender).call{value:_amount}("");
48-
if(!success){
46+
//transfer token to user
47+
(bool success,) = payable(msg.sender).call{value: _amount}("");
48+
if (!success) {
4949
revert Vault_TransferFailed();
5050
}
51-
// emit event
51+
// emit event
5252
emit Vault_EthRedeemed(msg.sender, _amount);
53-
}
53+
}
5454
// ------------ receiver ------------------
5555
/**
5656
* @notice if Eth is sent to the contract without function call
5757
*/
58+
5859
receive() external payable {} // when raw Eth is sent to the contract
5960

6061
/**

src/interfaces/IRebaseToken.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ interface IRebaseToken {
88
* @param _to The address to mint tokens to.
99
* @param _amount The amount of tokens to mint.
1010
*/
11-
function mint(address _to, uint256 _amount) external;
11+
function mint(address _to, uint256 _amount) external;
1212
/**
1313
* @notice Burns tokens from a specified address.
1414
* @param _from The address to burn tokens from.
@@ -17,4 +17,4 @@ interface IRebaseToken {
1717
function burn(address _from, uint256 _amount) external;
1818
// Note: We only include functions that the Vault contract will call.
1919
// Other functions from the actual RebaseToken.sol are not needed here.
20-
}
20+
}

0 commit comments

Comments
 (0)