-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
172 changed files
with
8,640 additions
and
2,919 deletions.
There are no files selected for viewing
Binary file removed
BIN
-31.7 KB
.yarn/cache/@chainsafe-as-sha256-npm-0.3.1-02546f2fc1-3bae7b4bc6.zip
Binary file not shown.
Binary file removed
BIN
-38 KB
.yarn/cache/@chainsafe-persistent-merkle-tree-npm-0.4.2-c1f20f4351-a7e59f80be.zip
Binary file not shown.
Binary file removed
BIN
-40.5 KB
.yarn/cache/@chainsafe-persistent-merkle-tree-npm-0.5.0-995d949fa7-c8a37eb2fb.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+29 KB
.yarn/cache/@foundry-rs-easy-foundryup-npm-0.1.3-e3da122086-a653a11e67.zip
Binary file not shown.
Binary file added
BIN
+48.7 KB
.yarn/cache/@foundry-rs-hardhat-anvil-npm-0.1.7-c167024ef2-148b5fdd30.zip
Binary file not shown.
Binary file added
BIN
+4.71 MB
.yarn/cache/@nomicfoundation-edr-darwin-arm64-npm-0.4.0-11c2423206-edb7500b8c.zip
Binary file not shown.
Binary file added
BIN
+4.95 MB
.yarn/cache/@nomicfoundation-edr-darwin-x64-npm-0.4.0-feafeebc00-ac80c8d2e1.zip
Binary file not shown.
Binary file added
BIN
+6.99 MB
.yarn/cache/@nomicfoundation-edr-linux-arm64-gnu-npm-0.4.0-2f3f0369b9-abb60f6fac.zip
Binary file not shown.
Binary file added
BIN
+6.94 MB
.yarn/cache/@nomicfoundation-edr-linux-arm64-musl-npm-0.4.0-1f8f3e1f11-c6e6329fb3.zip
Binary file not shown.
Binary file added
BIN
+6.95 MB
.yarn/cache/@nomicfoundation-edr-linux-x64-gnu-npm-0.4.0-aca8558ea8-8885a5815d.zip
Binary file not shown.
Binary file added
BIN
+6.94 MB
.yarn/cache/@nomicfoundation-edr-linux-x64-musl-npm-0.4.0-48b71162b7-cb4755f0fa.zip
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+5.05 MB
.yarn/cache/@nomicfoundation-edr-win32-x64-msvc-npm-0.4.0-7ca21bf40e-2cfd52eb7f.zip
Binary file not shown.
Binary file removed
BIN
-71 KB
.yarn/cache/@nomicfoundation-ethereumjs-block-npm-5.0.2-4d950628bb-e3d7c24aa1.zip
Binary file not shown.
Binary file removed
BIN
-640 KB
.yarn/cache/@nomicfoundation-ethereumjs-blockchain-npm-7.0.2-d9705709ea-4cc27cf1d3.zip
Binary file not shown.
Binary file removed
BIN
-119 KB
.yarn/cache/@nomicfoundation-ethereumjs-common-npm-4.0.2-2a486d4209-ea0199240a.zip
Binary file not shown.
Binary file added
BIN
+176 KB
.yarn/cache/@nomicfoundation-ethereumjs-common-npm-4.0.4-c84ef6a4e0-1daaede087.zip
Binary file not shown.
Binary file removed
BIN
-24.1 KB
.yarn/cache/@nomicfoundation-ethereumjs-ethash-npm-3.0.2-cc0ebd2006-c7d963a680.zip
Binary file not shown.
Binary file removed
BIN
-238 KB
.yarn/cache/@nomicfoundation-ethereumjs-evm-npm-2.0.2-f0d731b2a8-abcc280500.zip
Binary file not shown.
Binary file removed
BIN
-18.4 KB
.yarn/cache/@nomicfoundation-ethereumjs-rlp-npm-5.0.2-4779aec89a-ceb8202966.zip
Binary file not shown.
Binary file added
BIN
+43.9 KB
.yarn/cache/@nomicfoundation-ethereumjs-rlp-npm-5.0.4-b98abcc3ae-39fb26340b.zip
Binary file not shown.
Binary file removed
BIN
-52.6 KB
.yarn/cache/@nomicfoundation-ethereumjs-statemanager-npm-2.0.2-5465bc8cbc-0eb939c75a.zip
Binary file not shown.
Binary file removed
BIN
-103 KB
.yarn/cache/@nomicfoundation-ethereumjs-trie-npm-6.0.2-405eaf4fb6-f70b89e7f0.zip
Binary file not shown.
Binary file removed
BIN
-111 KB
.yarn/cache/@nomicfoundation-ethereumjs-tx-npm-5.0.2-d7824094e9-0feb40b602.zip
Binary file not shown.
Binary file added
BIN
+217 KB
.yarn/cache/@nomicfoundation-ethereumjs-tx-npm-5.0.4-67ff60a590-5e84de14fa.zip
Binary file not shown.
Binary file removed
BIN
-84.7 KB
.yarn/cache/@nomicfoundation-ethereumjs-util-npm-9.0.2-8b4899e586-ec687ecd96.zip
Binary file not shown.
Binary file added
BIN
+203 KB
.yarn/cache/@nomicfoundation-ethereumjs-util-npm-9.0.4-7086377bd2-891806c7ed.zip
Binary file not shown.
Binary file removed
BIN
-100 KB
.yarn/cache/@nomicfoundation-ethereumjs-vm-npm-7.0.2-cd9b4fb94e-7ad391bc68.zip
Binary file not shown.
Binary file added
BIN
+32.1 KB
.yarn/cache/@nomiclabs-hardhat-waffle-npm-2.0.6-3743b1a35f-55e5edd8dd.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed
BIN
-5.56 KB
.yarn/cache/@types-readable-stream-npm-2.3.15-d06d8380b8-49b51e56f9.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+5.39 KB
.yarn/cache/@types-sinonjs__fake-timers-npm-8.1.5-c35b400174-3a0b285fcb.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed
BIN
-62.6 KB
.yarn/cache/bigint-crypto-utils-npm-3.2.2-83a2d4b993-e7a3ccd915.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed
BIN
-11.8 KB
.yarn/cache/functional-red-black-tree-npm-1.0.1-ccfe924dcd-debe73e922.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+19.7 KB
.yarn/cache/ts-interface-checker-npm-0.1.13-0c7b064494-9f7346b9e2.zip
Binary file not shown.
This file contains 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,27 @@ | ||
name = "synthetix-snapshot-rewards" | ||
version = "<%= package.version %>" | ||
description = "Maintains snapshots of account balances in a pool" | ||
|
||
[setting.synthetixPackage] | ||
defaultValue = "synthetix:latest@main" | ||
|
||
[setting.servicePoolId] | ||
defaultValue = "0" | ||
|
||
[setting.serviceCollateralAddress] | ||
defaultValue = "<%= AddressZero %>" | ||
|
||
[setting.snapper] | ||
defaultValue = "<%= AddressZero %>" | ||
|
||
[import.synthetix] | ||
source = "<%= settings.synthetixPackage %>" | ||
|
||
[contract.RewardsDistributor] | ||
artifact = "SnapshotRewardsDistributor" | ||
args = [ | ||
"<%= imports.synthetix.contracts.CoreProxy.address %>", | ||
"<%= settings.servicePoolId %>", | ||
"<%= settings.serviceCollateralAddress %>", | ||
"<%= settings.snapper %>", | ||
] |
251 changes: 251 additions & 0 deletions
251
auxiliary/RewardsDistributor/src/SnapshotRewardsDistributor.sol
This file contains 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,251 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.13; | ||
|
||
import {ERC2771Context} from "@synthetixio/core-contracts/contracts/utils/ERC2771Context.sol"; | ||
import {IERC721} from "@synthetixio/core-contracts/contracts/interfaces/IERC721.sol"; | ||
import {IRewardDistributor} from "@synthetixio/main/contracts/interfaces/external/IRewardDistributor.sol"; | ||
import {AccessError} from "@synthetixio/core-contracts/contracts/errors/AccessError.sol"; | ||
import {ParameterError} from "@synthetixio/core-contracts/contracts/errors/ParameterError.sol"; | ||
import {IERC165} from "@synthetixio/core-contracts/contracts/interfaces/IERC165.sol"; | ||
import {ISnapshotRecord} from "@synthetixio/governance/contracts/interfaces/external/ISnapshotRecord.sol"; | ||
import {IAccountModule} from "@synthetixio/main/contracts/interfaces/IAccountModule.sol"; | ||
import {IVaultModule} from "@synthetixio/main/contracts/interfaces/IVaultModule.sol"; | ||
|
||
contract SnapshotRewardsDistributor is IRewardDistributor, ISnapshotRecord { | ||
error AccountNotFound(); | ||
|
||
address private rewardsManager; | ||
IERC721 private accountToken; | ||
uint128 public servicePoolId; | ||
address public serviceCollateralType; | ||
|
||
struct PeriodBalance { | ||
uint128 amount; | ||
uint128 periodId; | ||
address owner; | ||
} | ||
|
||
/** | ||
* Addresses selected by owner which are allowed to call `takeSnapshot` | ||
* `takeSnapshot` is not public because only a small number of snapshots can be retained for a period of time, and so they | ||
* must be controlled to prevent censorship | ||
*/ | ||
mapping(address => bool) public authorizedToSnapshot; | ||
|
||
/** | ||
* Records a user's balance as it changes from period to period. | ||
* The last item in the array always represents the user's most recent balance | ||
* The intermediate balance is only recorded if | ||
* `currentPeriodId` differs (which would happen upon a call to `setCurrentPeriodId`) | ||
*/ | ||
mapping(uint128 => PeriodBalance[]) public balances; | ||
|
||
/** | ||
* Records totalSupply as it changes from period to period | ||
* Similar to `balances`, the `totalSupplyOnPeriod` at index `currentPeriodId` matches the current total supply | ||
* Any other period ID would represent its most recent totalSupply before the period ID changed. | ||
*/ | ||
mapping(uint256 => uint256) public totalSupplyOnPeriod; | ||
|
||
/** | ||
* Records the latest address to which account it is part of | ||
*/ | ||
mapping(address => PeriodBalance[]) private accountBalances; | ||
|
||
uint128 public currentPeriodId; | ||
|
||
uint256 internal constant MAX_PERIOD_ITERATE = 30; | ||
|
||
constructor( | ||
address _rewardsManager, // SynthetixCoreProxy | ||
uint128 _servicePoolId, | ||
address _serviceCollateralType, | ||
address snapper | ||
) { | ||
servicePoolId = _servicePoolId; | ||
serviceCollateralType = _serviceCollateralType; | ||
rewardsManager = _rewardsManager; | ||
accountToken = IERC721(IAccountModule(rewardsManager).getAccountTokenAddress()); | ||
authorizedToSnapshot[snapper] = true; | ||
} | ||
|
||
function onPositionUpdated( | ||
uint128 accountId, | ||
uint128 poolId, | ||
address collateralType, | ||
uint256 // actorSharesD18 | ||
) external { | ||
address sender = ERC2771Context._msgSender(); | ||
if (sender != rewardsManager) { | ||
revert AccessError.Unauthorized(sender); | ||
} | ||
|
||
if (poolId != servicePoolId) { | ||
revert ParameterError.InvalidParameter( | ||
"poolId", | ||
"Pool does not match the rewards pool" | ||
); | ||
} | ||
|
||
if (collateralType != serviceCollateralType) { | ||
revert ParameterError.InvalidParameter( | ||
"collateralType", | ||
"Collateral does not match the rewards token" | ||
); | ||
} | ||
|
||
// get current account information | ||
uint256 newAmount = IVaultModule(rewardsManager).getPositionCollateral( | ||
accountId, | ||
poolId, | ||
collateralType | ||
); | ||
address account = accountToken.ownerOf(accountId); | ||
|
||
// ensure periods for all the values we will be updating are correct | ||
uint256 idIdx = updatePeriod(balances[accountId]); | ||
uint256 oldAccountIdx = updatePeriod(accountBalances[balances[accountId][idIdx].owner]); | ||
uint256 accountIdx = updatePeriod(accountBalances[account]); | ||
|
||
uint256 prevBalance = balances[accountId][idIdx].amount; | ||
|
||
// subtract balance from previous owner | ||
// solhint-disable-next-line | ||
accountBalances[balances[accountId][idIdx].owner][oldAccountIdx].amount -= uint128( | ||
prevBalance | ||
); | ||
|
||
// add balance to new owner | ||
// solhint-disable-next-line | ||
accountBalances[account][accountIdx].amount += uint128(newAmount); | ||
|
||
// update account id record | ||
// solhint-disable-next-line | ||
balances[accountId][idIdx].amount = uint128(newAmount); | ||
balances[accountId][idIdx].owner = account; | ||
|
||
totalSupplyOnPeriod[currentPeriodId] = | ||
totalSupplyOnPeriod[currentPeriodId] + | ||
newAmount - | ||
prevBalance; | ||
} | ||
|
||
function updatePeriod(PeriodBalance[] storage bals) internal returns (uint256) { | ||
uint256 balanceCount = bals.length; | ||
if (balanceCount == 0 || bals[balanceCount - 1].periodId != currentPeriodId) { | ||
// solhint-disable-next-line | ||
bals.push(PeriodBalance(0, uint128(currentPeriodId), address(0))); | ||
|
||
if (balanceCount > 0) { | ||
bals[balanceCount].amount = bals[balanceCount - 1].amount; | ||
bals[balanceCount].owner = bals[balanceCount - 1].owner; | ||
} | ||
|
||
balanceCount++; | ||
} | ||
|
||
return balanceCount - 1; | ||
} | ||
|
||
function balanceOfOnPeriod(address account, uint256 periodId) public view returns (uint256) { | ||
uint256 accountPeriodHistoryCount = accountBalances[account].length; | ||
// solhint-disable-next-line | ||
int256 oldestHistoryIterate = int256( | ||
MAX_PERIOD_ITERATE < accountPeriodHistoryCount | ||
? accountPeriodHistoryCount - MAX_PERIOD_ITERATE | ||
: 0 | ||
); | ||
int256 i; | ||
// solhint-disable-next-line | ||
for (i = int256(accountPeriodHistoryCount) - 1; i >= oldestHistoryIterate; i--) { | ||
// solhint-disable-next-line | ||
if (accountBalances[account][uint256(i)].periodId <= periodId) { | ||
// solhint-disable-next-line | ||
return uint256(accountBalances[account][uint256(i)].amount); | ||
} | ||
} | ||
|
||
if (i >= 0) { | ||
revert AccountNotFound(); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
function balanceOfOnPeriod(uint128 accountId, uint256 periodId) public view returns (uint256) { | ||
uint256 accountPeriodHistoryCount = balances[accountId].length; | ||
// solhint-disable-next-line | ||
int256 oldestHistoryIterate = int256( | ||
MAX_PERIOD_ITERATE < accountPeriodHistoryCount | ||
? accountPeriodHistoryCount - MAX_PERIOD_ITERATE | ||
: 0 | ||
); | ||
int256 i; | ||
// solhint-disable-next-line | ||
for (i = int256(accountPeriodHistoryCount) - 1; i >= oldestHistoryIterate; i--) { | ||
// solhint-disable-next-line | ||
if (balances[accountId][uint256(i)].periodId <= periodId) { | ||
// solhint-disable-next-line | ||
return uint256(balances[accountId][uint256(i)].amount); | ||
} | ||
} | ||
|
||
if (i >= 0) { | ||
revert AccountNotFound(); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
function balanceOf(uint128 accountId) external view returns (uint256) { | ||
return balanceOfOnPeriod(accountId, currentPeriodId); | ||
} | ||
|
||
function balanceOf(address user) external view returns (uint256) { | ||
return balanceOfOnPeriod(user, currentPeriodId); | ||
} | ||
|
||
function totalSupply() external view returns (uint256) { | ||
return totalSupplyOnPeriod[currentPeriodId]; | ||
} | ||
|
||
function takeSnapshot(uint128 id) external { | ||
address sender = ERC2771Context._msgSender(); | ||
if (!authorizedToSnapshot[sender]) { | ||
revert AccessError.Unauthorized(sender); | ||
} | ||
if (id <= currentPeriodId) { | ||
revert ParameterError.InvalidParameter("id", "period id must always increase"); | ||
} | ||
totalSupplyOnPeriod[id] = totalSupplyOnPeriod[currentPeriodId]; | ||
currentPeriodId = id; | ||
} | ||
|
||
function payout( | ||
uint128, // accountId | ||
uint128, // poolId_ | ||
address, // collateralType_ | ||
address, // payoutTarget_ | ||
uint256 // payoutAmount_ | ||
) external pure returns (bool) { | ||
// this is not a rewards distributor that pays out any tokens | ||
return true; | ||
} | ||
|
||
function name() public pure override returns (string memory) { | ||
return "snapshot tracker for governance"; | ||
} | ||
|
||
function token() public pure override returns (address) {} | ||
|
||
/** | ||
* @dev See {IERC165-supportsInterface}. | ||
*/ | ||
function supportsInterface( | ||
bytes4 interfaceId | ||
) public view virtual override(IERC165) returns (bool) { | ||
return | ||
interfaceId == type(IRewardDistributor).interfaceId || | ||
interfaceId == this.supportsInterface.selector; | ||
} | ||
} |
Oops, something went wrong.