Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
19860256 | 277 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
DirectGrantsLiteStrategy
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 400 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; // External Libraries import {Multicall} from "lib/openzeppelin-contracts/contracts/utils/Multicall.sol"; // Interfaces import {IRegistry} from "../../core/interfaces/IRegistry.sol"; // Core Contracts import {BaseStrategy} from "../BaseStrategy.sol"; // Internal Libraries import {Metadata} from "../../core/libraries/Metadata.sol"; import {Native} from "../../core/libraries/Native.sol"; // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⢿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⡟⠘⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣾⠻⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⡿⠀⠀⠸⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⢀⣠⣴⣴⣶⣶⣶⣦⣦⣀⡀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⡿⠃⠀⠙⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠁⠀⠀⠀⢻⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠘⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⠃⠀⠀⠀⠀⠈⢿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⣰⣿⣿⣿⡿⠋⠁⠀⠀⠈⠘⠹⣿⣿⣿⣿⣆⠀⠀⠀ // ⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡀⠀⠀ // ⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣟⠀⡀⢀⠀⡀⢀⠀⡀⢈⢿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⡇⠀⠀ // ⠀⠀⣠⣿⣿⣿⣿⣿⣿⡿⠋⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⡿⢿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣷⡀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠸⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠂⠀⠀ // ⠀⠀⠙⠛⠿⠻⠻⠛⠉⠀⠀⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣧⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⢻⣿⣿⣿⣷⣀⢀⠀⠀⠀⡀⣰⣾⣿⣿⣿⠏⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣧⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠹⢿⣿⣿⣿⣿⣾⣾⣷⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠃⠀⠀⠀⠀⠀⠀⠀⠀⠠⠿⠻⠟⠿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠟⠿⠟⠿⠆⠀⠸⠿⠿⠟⠯⠀⠀⠀⠸⠿⠿⠿⠏⠀⠀⠀⠀⠀⠈⠉⠻⠻⡿⣿⢿⡿⡿⠿⠛⠁⠀⠀⠀⠀⠀⠀ // allo.gitcoin.co /// @title Direct Grants Lite Strategy /// @author @thelostone-mc <[email protected]>, @0xKurt <[email protected]>, @codenamejason <[email protected]> /// @notice Strategy for direct grants contract DirectGrantsLiteStrategy is Native, BaseStrategy, Multicall { /// ================================ /// ========== Struct ============== /// ================================ /// @notice Struct to hold details of the application status /// @dev Application status is stored in a bitmap. Each 4 bits represents the status of a recipient, /// defined as 'index' here. The first 4 bits of the 256 bits represent the status of the first recipient, /// the second 4 bits represent the status of the second recipient, and so on. /// /// The 'rowIndex' is the index of the row in the bitmap, and the 'statusRow' is the value of the row. /// The 'statusRow' is updated when the status of a recipient changes. /// /// Note: Since we need 4 bits to store a status, one row of the bitmap can hold the status information of 256/4 recipients. /// /// For example, if we have 5 recipients, the bitmap will look like this: /// | recipient1 | recipient2 | recipient3 | recipient4 | recipient5 | 'rowIndex' /// | 0000 | 0001 | 0010 | 0011 | 0100 | 'statusRow' /// | none | pending | accepted | rejected | appealed | converted status (0, 1, 2, 3, 4) /// struct ApplicationStatus { uint256 index; uint256 statusRow; } /// @notice Stores the details of the recipients. struct Recipient { // If false, the recipientAddress is the anchor of the profile bool useRegistryAnchor; address recipientAddress; Metadata metadata; } /// @notice Stores the details of the allocation. struct Allocation { address token; address recipientId; uint256 amount; } /// @notice Stores the initialize data for the strategy struct InitializeData { bool useRegistryAnchor; bool metadataRequired; uint64 registrationStartTime; uint64 registrationEndTime; } /// =============================== /// ========== Events ============= /// =============================== /// @notice Emitted when a recipient updates their registration /// @param recipientId Id of the recipient /// @param data The encoded data - (address recipientId, address recipientAddress, Metadata metadata) /// @param sender The sender of the transaction /// @param status The updated status of the recipient event UpdatedRegistration(address indexed recipientId, bytes data, address sender, uint8 status); /// @notice Emitted when a recipient is registered and the status is updated /// @param rowIndex The index of the row in the bitmap /// @param fullRow The value of the row /// @param sender The sender of the transaction event RecipientStatusUpdated(uint256 indexed rowIndex, uint256 fullRow, address sender); /// @notice Emitted when the timestamps are updated /// @param registrationStartTime The start time for the registration /// @param registrationEndTime The end time for the registration /// @param sender The sender of the transaction event TimestampsUpdated(uint64 registrationStartTime, uint64 registrationEndTime, address sender); /// ================================ /// ========== Storage ============= /// ================================ /// @notice Flag to indicate whether to use the registry anchor or not. bool public useRegistryAnchor; /// @notice Flag to indicate whether metadata is required or not. bool public metadataRequired; /// @notice The timestamps in seconds for the start and end times. uint64 public registrationStartTime; uint64 public registrationEndTime; /// @notice The total number of recipients. uint256 public recipientsCounter; /// @notice The registry contract interface. IRegistry private _registry; /// @notice This is a packed array of booleans, 'statuses[0]' is the first row of the bitmap and allows to /// store 256 bits to describe the status of 256 projects. 'statuses[1]' is the second row, and so on /// Instead of using 1 bit for each recipient status, we will use 4 bits for each status /// to allow 7 statuses: /// 0: none /// 1: pending /// 2: accepted /// 3: rejected /// 4: appealed /// 5: in review /// 6: canceled /// Since it's a mapping the storage it's pre-allocated with zero values, so if we check the /// status of an existing recipient, the value is by default 0 (none). /// If we want to check the status of a recipient, we take its index from the `recipients` array /// and convert it to the 2-bits position in the bitmap. mapping(uint256 => uint256) public statusesBitMap; /// @notice 'recipientId' => 'statusIndex' /// @dev 'statusIndex' is the index of the recipient in the 'statusesBitMap' bitmap. mapping(address => uint256) public recipientToStatusIndexes; /// @notice 'recipientId' => 'Recipient' struct. mapping(address => Recipient) internal _recipients; /// ================================ /// ========== Modifier ============ /// ================================ /// @notice Modifier to check if the registration is active /// @dev This will revert if the registration has not started or if the registration has ended. modifier onlyActiveRegistration() { _checkOnlyActiveRegistration(); _; } /// =============================== /// ======== Constructor ========== /// =============================== /// @notice Constructor for the Direct Grants Lite Strategy /// @param _allo The 'Allo' contract /// @param _name The name of the strategy constructor(address _allo, string memory _name) BaseStrategy(_allo, _name) {} /// =============================== /// ========= Initialize ========== /// =============================== /// @notice Initializes the strategy /// @dev This will revert if the strategy is already initialized and 'msg.sender' is not the 'Allo' contract. /// @param _poolId The 'poolId' to initialize /// @param _data The data to be decoded to initialize the strategy /// @custom:data InitializeData(bool _useRegistryAnchor, bool _metadataRequired, uint64 _registrationStartTime, /// uint64 _registrationEndTime) function initialize(uint256 _poolId, bytes memory _data) external virtual override onlyAllo { InitializeData memory initializeData = abi.decode(_data, (InitializeData)); __DirectGrantsLiteStrategy_init(_poolId, initializeData); emit Initialized(_poolId, _data); } /// @notice Initializes this strategy as well as the BaseStrategy. /// @dev This will revert if the strategy is already initialized. Emits a 'TimestampsUpdated()' event. /// @param _poolId The 'poolId' to initialize /// @param _initializeData The data to be decoded to initialize the strategy function __DirectGrantsLiteStrategy_init(uint256 _poolId, InitializeData memory _initializeData) internal { // Initialize the BaseStrategy with the '_poolId' __BaseStrategy_init(_poolId); // Initialize required values useRegistryAnchor = _initializeData.useRegistryAnchor; metadataRequired = _initializeData.metadataRequired; _registry = allo.getRegistry(); // Set the updated timestamps registrationStartTime = _initializeData.registrationStartTime; registrationEndTime = _initializeData.registrationEndTime; recipientsCounter = 1; // If the timestamps are invalid this will revert - See details in '_isPoolTimestampValid' _isPoolTimestampValid(_initializeData.registrationStartTime, _initializeData.registrationEndTime); // Emit that the timestamps have been updated with the updated values emit TimestampsUpdated(_initializeData.registrationStartTime, _initializeData.registrationEndTime, msg.sender); } /// =============================== /// ============ Views ============ /// =============================== /// @notice Get a recipient with a '_recipientId' /// @param _recipientId ID of the recipient /// @return recipient The recipient details function getRecipient(address _recipientId) external view returns (Recipient memory recipient) { return _getRecipient(_recipientId); } /// @notice Get recipient status /// @dev This will return the 'Status' of the recipient, the 'Status' is used at the strategy /// level and is different from the 'Status' which is used at the protocol level /// @param _recipientId ID of the recipient /// @return Status of the recipient function _getRecipientStatus(address _recipientId) internal view override returns (Status) { return Status(_getUintRecipientStatus(_recipientId)); } /// =============================== /// ======= External/Custom ======= /// =============================== /// @notice Sets recipient statuses. /// @dev The statuses are stored in a bitmap of 4 bits for each recipient. The first 4 bits of the 256 bits represent /// the status of the first recipient, the second 4 bits represent the status of the second recipient, and so on. /// 'msg.sender' must be a pool manager. /// Statuses: /// - 0: none /// - 1: pending /// - 2: accepted /// - 3: rejected /// - 4: appealed /// - 5: in review /// - 6: canceled /// Emits the RecipientStatusUpdated() event. /// @param statuses new statuses /// @param refRecipientsCounter the recipientCounter the transaction is based on function reviewRecipients(ApplicationStatus[] memory statuses, uint256 refRecipientsCounter) external onlyPoolManager(msg.sender) { if (refRecipientsCounter != recipientsCounter) revert INVALID(); // Loop through the statuses and set the status uint256 length = statuses.length; for (uint256 i; i < length;) { uint256 rowIndex = statuses[i].index; uint256 fullRow = statuses[i].statusRow; statusesBitMap[rowIndex] = fullRow; // Emit that the recipient status has been updated with the values emit RecipientStatusUpdated(rowIndex, fullRow, msg.sender); unchecked { i++; } } } /// @notice Sets the start and end dates. /// @dev The timestamps are in seconds for the start and end times. The 'msg.sender' must be a pool manager. /// Emits a 'TimestampsUpdated()' event. /// @param _registrationStartTime The start time for the registration /// @param _registrationEndTime The end time for the registration function updatePoolTimestamps(uint64 _registrationStartTime, uint64 _registrationEndTime) external onlyPoolManager(msg.sender) { // If the timestamps are invalid this will revert - See details in '_isPoolTimestampValid' _isPoolTimestampValid(_registrationStartTime, _registrationEndTime); // Set the updated timestamps registrationStartTime = _registrationStartTime; registrationEndTime = _registrationEndTime; // Emit that the timestamps have been updated with the updated values emit TimestampsUpdated(registrationStartTime, registrationEndTime, msg.sender); } /// @notice Withdraw funds from pool /// @param _token The token to be withdrawn function withdraw(address _token) external onlyPoolManager(msg.sender) { // get the actual balance hold by the pool uint256 amount = _getBalance(_token, address(this)); // calculate the amount which is accessible uint256 accessibleAmount = amount; // transfer the amount to the pool manager _transferAmount(_token, msg.sender, accessibleAmount); } /// ==================================== /// ============ Internal ============== /// ==================================== /// @notice Checks if the registration is active and reverts if not. /// @dev This will revert if the registration has not started or if the registration has ended. function _checkOnlyActiveRegistration() internal view { if (registrationStartTime > block.timestamp || block.timestamp > registrationEndTime) { revert REGISTRATION_NOT_ACTIVE(); } } /// @notice Checks if address is eligible allocator. /// @return True, if address is pool manager, otherwise false. function _isValidAllocator(address allocator) internal view override returns (bool) { return allo.isPoolManager(poolId, allocator); } /// @notice Checks if the timestamps are valid. /// @dev This will revert if any of the timestamps are invalid. This is determined by the strategy /// and may vary from strategy to strategy. Checks if '_registrationStartTime' is greater than the '_registrationEndTime' /// @param _registrationStartTime The start time for the registration /// @param _registrationEndTime The end time for the registration function _isPoolTimestampValid(uint64 _registrationStartTime, uint64 _registrationEndTime) internal pure { if (_registrationStartTime > _registrationEndTime) { revert INVALID(); } } /// @notice Checks whether a pool is active or not. /// @dev This will return true if the current 'block timestamp' is greater than or equal to the /// 'registrationStartTime' and less than or equal to the 'registrationEndTime'. /// @return 'true' if pool is active, otherwise 'false' function _isPoolActive() internal view override returns (bool) { if (registrationStartTime <= block.timestamp && block.timestamp <= registrationEndTime) { return true; } return false; } /// @notice Submit recipient to pool and set their status. /// @param _data The data to be decoded. /// @custom:data if 'useRegistryAnchor' is 'true' (address recipientId, address recipientAddress, Metadata metadata) /// @custom:data if 'useRegistryAnchor' is 'false' (address registryAnchor, address recipientAddress, Metadata metadata) /// @param _sender The sender of the transaction /// @return recipientId The ID of the recipient function _registerRecipient(bytes memory _data, address _sender) internal override onlyActiveRegistration returns (address recipientId) { if (msg.value != 0) revert NON_ZERO_VALUE(); bool isUsingRegistryAnchor; address recipientAddress; address registryAnchor; Metadata memory metadata; // decode data custom to this strategy if (useRegistryAnchor) { (recipientId, recipientAddress, metadata) = abi.decode(_data, (address, address, Metadata)); // If the sender is not a profile member this will revert if (!_isProfileMember(recipientId, _sender)) { revert UNAUTHORIZED(); } } else { (registryAnchor, recipientAddress, metadata) = abi.decode(_data, (address, address, Metadata)); // Set this to 'true' if the registry anchor is not the zero address isUsingRegistryAnchor = registryAnchor != address(0); // If using the 'registryAnchor' we set the 'recipientId' to the 'registryAnchor', otherwise we set it to the 'msg.sender' recipientId = isUsingRegistryAnchor ? registryAnchor : _sender; // Checks if the '_sender' is a member of the profile 'anchor' being used and reverts if not if (isUsingRegistryAnchor && !_isProfileMember(recipientId, _sender)) { revert UNAUTHORIZED(); } } // If the metadata is required and the metadata is invalid this will revert if (metadataRequired && (bytes(metadata.pointer).length == 0 || metadata.protocol == 0)) { revert INVALID_METADATA(); } // If the recipient address is the zero address this will revert if (recipientAddress == address(0)) { revert RECIPIENT_ERROR(recipientId); } // Get the recipient Recipient storage recipient = _recipients[recipientId]; // update the recipients data recipient.recipientAddress = recipientAddress; recipient.metadata = metadata; recipient.useRegistryAnchor = useRegistryAnchor ? true : isUsingRegistryAnchor; if (recipientToStatusIndexes[recipientId] == 0) { // recipient registering new application recipientToStatusIndexes[recipientId] = recipientsCounter; _setRecipientStatus(recipientId, uint8(Status.Pending)); bytes memory extendedData = abi.encode(_data, recipientsCounter); emit Registered(recipientId, extendedData, _sender); recipientsCounter++; } else { uint8 currentStatus = _getUintRecipientStatus(recipientId); if (currentStatus == uint8(Status.Accepted) || currentStatus == uint8(Status.InReview)) { // recipient updating accepted application _setRecipientStatus(recipientId, uint8(Status.Pending)); } else if (currentStatus == uint8(Status.Rejected)) { // recipient updating rejected application _setRecipientStatus(recipientId, uint8(Status.Appealed)); } emit UpdatedRegistration(recipientId, _data, _sender, _getUintRecipientStatus(recipientId)); } } /// @notice Distribute funds to recipients. /// @dev This function reverts by default function _distribute(address[] memory, bytes memory, address) internal virtual override { revert NOT_IMPLEMENTED(); } /// @notice Allocate. Required by the 'BaseStrategy'. /// @param _data The data to be decoded /// @custom:data '(Allocation[] allocations)' /// @param _sender The sender of the transaction function _allocate(bytes memory _data, address _sender) internal virtual override onlyPoolManager(_sender) { uint256 nativeAmount = msg.value; // Decode the allocation data (Allocation[] memory allocations) = abi.decode(_data, (Allocation[])); uint256 length = allocations.length; if (length == 0) revert INVALID(); // nothing to allocate for (uint256 i = 0; i < length;) { Allocation memory allocation = allocations[i]; address recipientId = allocation.recipientId; Recipient memory recipient = _getRecipient(recipientId); address recipientAddress = recipient.recipientAddress; address token = allocations[i].token; uint256 amount = allocations[i].amount; // This will revert if the sender tries to spend more than the msg.value if (token == NATIVE) nativeAmount -= amount; if (recipient.recipientAddress == address(0)) { revert RECIPIENT_ERROR(recipientId); } if (_getUintRecipientStatus(recipientId) != uint8(Status.Accepted)) { revert RECIPIENT_NOT_ACCEPTED(); } _transferAmountFrom(token, TransferData({from: _sender, to: recipientAddress, amount: amount})); emit Allocated(recipientId, amount, token, _sender); unchecked { ++i; } } if (nativeAmount > 0) _transferAmount(NATIVE, _sender, nativeAmount); } /// @notice Check if sender is profile owner or member. /// @param _anchor Anchor of the profile /// @param _sender The sender of the transaction /// @return 'true' if the '_sender' is a profile member, otherwise 'false' function _isProfileMember(address _anchor, address _sender) internal view virtual returns (bool) { IRegistry.Profile memory profile = _registry.getProfileByAnchor(_anchor); return _registry.isOwnerOrMemberOfProfile(profile.id, _sender); } /// @notice Get the recipient details. /// @param _recipientId Id of the recipient /// @return Recipient details function _getRecipient(address _recipientId) internal view returns (Recipient memory) { return _recipients[_recipientId]; } /// @notice Returns the payout summary for the accepted recipient. /// @dev This will revert by default. function _getPayout(address, bytes memory) internal pure override returns (PayoutSummary memory) { revert NOT_IMPLEMENTED(); } /// @notice Set the recipient status. /// @param _recipientId ID of the recipient /// @param _status Status of the recipient function _setRecipientStatus(address _recipientId, uint256 _status) internal { // Get the row index, column index and current row (uint256 rowIndex, uint256 colIndex, uint256 currentRow) = _getStatusRowColumn(_recipientId); // Calculate the 'newRow' uint256 newRow = currentRow & ~(15 << colIndex); // Add the status to the mapping statusesBitMap[rowIndex] = newRow | (_status << colIndex); } /// @notice Get recipient status /// @param _recipientId ID of the recipient /// @return status The status of the recipient function _getUintRecipientStatus(address _recipientId) internal view returns (uint8 status) { if (recipientToStatusIndexes[_recipientId] == 0) return 0; // Get the column index and current row (, uint256 colIndex, uint256 currentRow) = _getStatusRowColumn(_recipientId); // Get the status from the 'currentRow' shifting by the 'colIndex' status = uint8((currentRow >> colIndex) & 15); // Return the status return status; } /// @notice Get recipient status 'rowIndex', 'colIndex' and 'currentRow'. /// @param _recipientId ID of the recipient /// @return (rowIndex, colIndex, currentRow) function _getStatusRowColumn(address _recipientId) internal view returns (uint256, uint256, uint256) { uint256 recipientIndex = recipientToStatusIndexes[_recipientId] - 1; uint256 rowIndex = recipientIndex / 64; // 256 / 4 uint256 colIndex = (recipientIndex % 64) * 4; return (rowIndex, colIndex, statusesBitMap[rowIndex]); } /// @notice Contract should be able to receive NATIVE receive() external payable { _checkOnlyAllo(); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.19; // Interfaces import {IRegistry} from "./IRegistry.sol"; import {IStrategy} from "./IStrategy.sol"; // Internal Libraries import {Metadata} from "../libraries/Metadata.sol"; // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⢿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⡟⠘⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣾⠻⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⡿⠀⠀⠸⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⢀⣠⣴⣴⣶⣶⣶⣦⣦⣀⡀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⡿⠃⠀⠙⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠁⠀⠀⠀⢻⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠘⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⠃⠀⠀⠀⠀⠈⢿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⣰⣿⣿⣿⡿⠋⠁⠀⠀⠈⠘⠹⣿⣿⣿⣿⣆⠀⠀⠀ // ⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡀⠀⠀ // ⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣟⠀⡀⢀⠀⡀⢀⠀⡀⢈⢿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⡇⠀⠀ // ⠀⠀⣠⣿⣿⣿⣿⣿⣿⡿⠋⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⡿⢿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣷⡀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠸⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠂⠀⠀ // ⠀⠀⠙⠛⠿⠻⠻⠛⠉⠀⠀⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣧⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⢻⣿⣿⣿⣷⣀⢀⠀⠀⠀⡀⣰⣾⣿⣿⣿⠏⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣧⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠹⢿⣿⣿⣿⣿⣾⣾⣷⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠃⠀⠀⠀⠀⠀⠀⠀⠀⠠⠿⠻⠟⠿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠟⠿⠟⠿⠆⠀⠸⠿⠿⠟⠯⠀⠀⠀⠸⠿⠿⠿⠏⠀⠀⠀⠀⠀⠈⠉⠻⠻⡿⣿⢿⡿⡿⠿⠛⠁⠀⠀⠀⠀⠀⠀ // allo.gitcoin.co /// @title Allo Interface /// @author @thelostone-mc <[email protected]>, @0xKurt <[email protected]>, @codenamejason <[email protected]>, @0xZakk <[email protected]>, @nfrgosselin <[email protected]> /// @notice Interface for the Allo contract. It exposes all functions needed to use the Allo protocol. interface IAllo { /// ====================== /// ======= Structs ====== /// ====================== /// @notice the Pool struct that all strategy pools are based from struct Pool { bytes32 profileId; IStrategy strategy; address token; Metadata metadata; bytes32 managerRole; bytes32 adminRole; } /// ====================== /// ======= Events ======= /// ====================== /// @notice Event emitted when a new pool is created /// @param poolId ID of the pool created /// @param profileId ID of the profile the pool is associated with /// @param strategy Address of the strategy contract /// @param token Address of the token pool was funded with when created /// @param amount Amount pool was funded with when created /// @param metadata Pool metadata event PoolCreated( uint256 indexed poolId, bytes32 indexed profileId, IStrategy strategy, address token, uint256 amount, Metadata metadata ); /// @notice Emitted when a pools metadata is updated /// @param poolId ID of the pool updated /// @param metadata Pool metadata that was updated event PoolMetadataUpdated(uint256 indexed poolId, Metadata metadata); /// @notice Emitted when a pool is funded /// @param poolId ID of the pool funded /// @param amount Amount funded to the pool /// @param fee Amount of the fee paid to the treasury event PoolFunded(uint256 indexed poolId, uint256 amount, uint256 fee); /// @notice Emitted when the base fee is paid /// @param poolId ID of the pool the base fee was paid for /// @param amount Amount of the base fee paid event BaseFeePaid(uint256 indexed poolId, uint256 amount); /// @notice Emitted when the treasury address is updated /// @param treasury Address of the new treasury event TreasuryUpdated(address treasury); /// @notice Emitted when the percent fee is updated /// @param percentFee New percentage for the fee event PercentFeeUpdated(uint256 percentFee); /// @notice Emitted when the base fee is updated /// @param baseFee New base fee amount event BaseFeeUpdated(uint256 baseFee); /// @notice Emitted when the registry address is updated /// @param registry Address of the new registry event RegistryUpdated(address registry); /// @notice Emitted when a strategy is approved and added to the cloneable strategies /// @param strategy Address of the strategy approved event StrategyApproved(address strategy); /// @notice Emitted when a strategy is removed from the cloneable strategies /// @param strategy Address of the strategy removed event StrategyRemoved(address strategy); /// ==================================== /// ==== External/Public Functions ===== /// ==================================== /// @notice Initialize the Allo contract /// @param _owner Address of the owner /// @param _registry Address of the registry contract /// @param _treasury Address of the treasury /// @param _percentFee Percentage for the fee /// @param _baseFee Base fee amount function initialize( address _owner, address _registry, address payable _treasury, uint256 _percentFee, uint256 _baseFee ) external; /// @notice Creates a new pool (with a custom strategy) /// @dev 'msg.sender' must be a member or owner of a profile to create a pool with or without a custom strategy, The encoded data /// will be specific to a given strategy requirements, reference the strategy implementation of 'initialize()'. The strategy /// address passed must not be a cloneable strategy. The strategy address passed must not be the zero address. 'msg.sender' must /// be a member or owner of the profile id passed as '_profileId'. /// @param _profileId The 'profileId' of the registry profile, used to check if 'msg.sender' is a member or owner of the profile /// @param _strategy The address of the deployed custom strategy /// @param _initStrategyData The data to initialize the strategy /// @param _token The address of the token you want to use in your pool /// @param _amount The amount of the token you want to deposit into the pool on initialization /// @param _metadata The 'Metadata' of the pool, this uses our 'Meatdata.sol' struct (consistent throughout the protocol) /// @param _managers The managers of the pool, and can be added/removed later by the pool admin /// @return poolId The ID of the pool function createPoolWithCustomStrategy( bytes32 _profileId, address _strategy, bytes memory _initStrategyData, address _token, uint256 _amount, Metadata memory _metadata, address[] memory _managers ) external payable returns (uint256 poolId); /// @notice Creates a new pool (by cloning a cloneable strategies). /// @dev 'msg.sender' must be owner or member of the profile id passed as '_profileId'. /// @param _profileId The ID of the registry profile, used to check if 'msg.sender' is a member or owner of the profile /// @param _strategy The address of the strategy contract the pool will use. /// @param _initStrategyData The data to initialize the strategy /// @param _token The address of the token /// @param _amount The amount of the token /// @param _metadata The metadata of the pool /// @param _managers The managers of the pool /// @custom:initstrategydata The encoded data will be specific to a given strategy requirements, /// reference the strategy implementation of 'initialize()' function createPool( bytes32 _profileId, address _strategy, bytes memory _initStrategyData, address _token, uint256 _amount, Metadata memory _metadata, address[] memory _managers ) external payable returns (uint256 poolId); /// @notice Updates a pools metadata. /// @dev 'msg.sender' must be a pool admin. /// @param _poolId The ID of the pool to update /// @param _metadata The new metadata to set function updatePoolMetadata(uint256 _poolId, Metadata memory _metadata) external; /// @notice Update the registry address. /// @dev 'msg.sender' must be the Allo contract owner. /// @param _registry The new registry address function updateRegistry(address _registry) external; /// @notice Updates the treasury address. /// @dev 'msg.sender' must be the Allo contract owner. /// @param _treasury The new treasury address function updateTreasury(address payable _treasury) external; /// @notice Updates the percentage for the fee. /// @dev 'msg.sender' must be the Allo contract owner. /// @param _percentFee The new percentage for the fee function updatePercentFee(uint256 _percentFee) external; /// @notice Updates the base fee. /// @dev 'msg.sender' must be the Allo contract owner. /// @param _baseFee The new base fee function updateBaseFee(uint256 _baseFee) external; /// @notice Adds a strategy to the cloneable strategies. /// @dev 'msg.sender' must be the Allo contract owner. /// @param _strategy The address of the strategy to add function addToCloneableStrategies(address _strategy) external; /// @notice Removes a strategy from the cloneable strategies. /// @dev 'msg.sender' must be the Allo contract owner. /// @param _strategy The address of the strategy to remove function removeFromCloneableStrategies(address _strategy) external; /// @notice Adds a pool manager to the pool. /// @dev 'msg.sender' must be a pool admin. /// @param _poolId The ID of the pool to add the manager to /// @param _manager The address of the manager to add function addPoolManager(uint256 _poolId, address _manager) external; /// @notice Removes a pool manager from the pool. /// @dev 'msg.sender' must be a pool admin. /// @param _poolId The ID of the pool to remove the manager from /// @param _manager The address of the manager to remove function removePoolManager(uint256 _poolId, address _manager) external; /// @notice Recovers funds from a pool. /// @dev 'msg.sender' must be a pool admin. /// @param _token The token to recover /// @param _recipient The address to send the recovered funds to function recoverFunds(address _token, address _recipient) external; /// @notice Registers a recipient and emits {Registered} event if successful and may be handled differently by each strategy. /// @param _poolId The ID of the pool to register the recipient for function registerRecipient(uint256 _poolId, bytes memory _data) external payable returns (address); /// @notice Registers a batch of recipients. /// @param _poolIds The pool ID's to register the recipients for /// @param _data The data to pass to the strategy and may be handled differently by each strategy function batchRegisterRecipient(uint256[] memory _poolIds, bytes[] memory _data) external returns (address[] memory); /// @notice Funds a pool. /// @dev 'msg.value' must be greater than 0 if the token is the native token /// or '_amount' must be greater than 0 if the token is not the native token. /// @param _poolId The ID of the pool to fund /// @param _amount The amount to fund the pool with function fundPool(uint256 _poolId, uint256 _amount) external payable; /// @notice Allocates funds to a recipient. /// @dev Each strategy will handle the allocation of funds differently. /// @param _poolId The ID of the pool to allocate funds from /// @param _data The data to pass to the strategy and may be handled differently by each strategy. function allocate(uint256 _poolId, bytes memory _data) external payable; /// @notice Allocates funds to multiple recipients. /// @dev Each strategy will handle the allocation of funds differently function batchAllocate(uint256[] calldata _poolIds, bytes[] memory _datas) external; /// @notice Distributes funds to recipients and emits {Distributed} event if successful /// @dev Each strategy will handle the distribution of funds differently /// @param _poolId The ID of the pool to distribute from /// @param _recipientIds The recipient ids to distribute to /// @param _data The data to pass to the strategy and may be handled differently by each strategy function distribute(uint256 _poolId, address[] memory _recipientIds, bytes memory _data) external; /// ========================= /// ==== View Functions ===== /// ========================= /// @notice Checks if an address is a pool admin. /// @param _poolId The ID of the pool to check /// @param _address The address to check /// @return 'true' if the '_address' is a pool admin, otherwise 'false' function isPoolAdmin(uint256 _poolId, address _address) external view returns (bool); /// @notice Checks if an address is a pool manager. /// @param _poolId The ID of the pool to check /// @param _address The address to check /// @return 'true' if the '_address' is a pool manager, otherwise 'false' function isPoolManager(uint256 _poolId, address _address) external view returns (bool); /// @notice Checks if a strategy is cloneable (is in the cloneableStrategies mapping). /// @param _strategy The address of the strategy to check /// @return 'true' if the '_strategy' is cloneable, otherwise 'false' function isCloneableStrategy(address _strategy) external view returns (bool); /// @notice Returns the address of the strategy for a given 'poolId' /// @param _poolId The ID of the pool to check /// @return strategy The address of the strategy for the ID of the pool passed in function getStrategy(uint256 _poolId) external view returns (address); /// @notice Returns the current percent fee /// @return percentFee The current percentage for the fee function getPercentFee() external view returns (uint256); /// @notice Returns the current base fee /// @return baseFee The current base fee function getBaseFee() external view returns (uint256); /// @notice Returns the current treasury address /// @return treasury The current treasury address function getTreasury() external view returns (address payable); /// @notice Returns the current registry address /// @return registry The current registry address function getRegistry() external view returns (IRegistry); /// @notice Returns the 'Pool' struct for a given 'poolId' /// @param _poolId The ID of the pool to check /// @return pool The 'Pool' struct for the ID of the pool passed in function getPool(uint256 _poolId) external view returns (Pool memory); /// @notice Returns the current fee denominator /// @dev 1e18 represents 100% /// @return feeDenominator The current fee denominator function getFeeDenominator() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.19; // Internal Libraries import {Metadata} from "../libraries/Metadata.sol"; // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⢿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⡟⠘⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣾⠻⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⡿⠀⠀⠸⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⢀⣠⣴⣴⣶⣶⣶⣦⣦⣀⡀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⡿⠃⠀⠙⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠁⠀⠀⠀⢻⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠘⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⠃⠀⠀⠀⠀⠈⢿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⣰⣿⣿⣿⡿⠋⠁⠀⠀⠈⠘⠹⣿⣿⣿⣿⣆⠀⠀⠀ // ⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡀⠀⠀ // ⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣟⠀⡀⢀⠀⡀⢀⠀⡀⢈⢿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⡇⠀⠀ // ⠀⠀⣠⣿⣿⣿⣿⣿⣿⡿⠋⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⡿⢿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣷⡀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠸⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠂⠀⠀ // ⠀⠀⠙⠛⠿⠻⠻⠛⠉⠀⠀⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣧⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⢻⣿⣿⣿⣷⣀⢀⠀⠀⠀⡀⣰⣾⣿⣿⣿⠏⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣧⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠹⢿⣿⣿⣿⣿⣾⣾⣷⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠃⠀⠀⠀⠀⠀⠀⠀⠀⠠⠿⠻⠟⠿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠟⠿⠟⠿⠆⠀⠸⠿⠿⠟⠯⠀⠀⠀⠸⠿⠿⠿⠏⠀⠀⠀⠀⠀⠈⠉⠻⠻⡿⣿⢿⡿⡿⠿⠛⠁⠀⠀⠀⠀⠀⠀ // allo.gitcoin.co /// @title IRegistry Interface /// @author @thelostone-mc <[email protected]>, @0xKurt <[email protected]>, @codenamejason <[email protected]>, @0xZakk <[email protected]>, @nfrgosselin <[email protected]> /// @notice Interface for the Registry contract and exposes all functions needed to use the Registry /// within the Allo protocol. /// @dev The Registry Interface is used to interact with the Allo protocol and create profiles /// that can be used to interact with the Allo protocol. The Registry is the main contract /// that all other contracts interact with to get the 'Profile' information needed to /// interact with the Allo protocol. The Registry is also used to create new profiles /// and update existing profiles. The Registry is also used to add and remove members /// from a profile. The Registry will not always be used in a strategy and will depend on /// the strategy being used. interface IRegistry { /// ====================== /// ======= Structs ====== /// ====================== /// @dev The Profile struct that all profiles are based from struct Profile { bytes32 id; uint256 nonce; string name; Metadata metadata; address owner; address anchor; } /// ====================== /// ======= Events ======= /// ====================== /// @dev Emitted when a profile is created. This will return your anchor address. event ProfileCreated( bytes32 indexed profileId, uint256 nonce, string name, Metadata metadata, address owner, address anchor ); /// @dev Emitted when a profile name is updated. This will update the anchor when the name is updated and return it. event ProfileNameUpdated(bytes32 indexed profileId, string name, address anchor); /// @dev Emitted when a profile's metadata is updated. event ProfileMetadataUpdated(bytes32 indexed profileId, Metadata metadata); /// @dev Emitted when a profile owner is updated. event ProfileOwnerUpdated(bytes32 indexed profileId, address owner); /// @dev Emitted when a profile pending owner is updated. event ProfilePendingOwnerUpdated(bytes32 indexed profileId, address pendingOwner); /// ========================= /// ==== View Functions ===== /// ========================= /// @dev Returns the 'Profile' for a '_profileId' passed /// @param _profileId The 'profileId' to return the 'Profile' for /// @return profile The 'Profile' for the '_profileId' passed function getProfileById(bytes32 _profileId) external view returns (Profile memory profile); /// @dev Returns the 'Profile' for an '_anchor' passed /// @param _anchor The 'anchor' to return the 'Profile' for /// @return profile The 'Profile' for the '_anchor' passed function getProfileByAnchor(address _anchor) external view returns (Profile memory profile); /// @dev Returns a boolean if the '_account' is a member or owner of the '_profileId' passed in /// @param _profileId The 'profileId' to check if the '_account' is a member or owner of /// @param _account The 'account' to check if they are a member or owner of the '_profileId' passed in /// @return isOwnerOrMemberOfProfile A boolean if the '_account' is a member or owner of the '_profileId' passed in function isOwnerOrMemberOfProfile(bytes32 _profileId, address _account) external view returns (bool isOwnerOrMemberOfProfile); /// @dev Returns a boolean if the '_account' is an owner of the '_profileId' passed in /// @param _profileId The 'profileId' to check if the '_account' is an owner of /// @param _owner The 'owner' to check if they are an owner of the '_profileId' passed in /// @return isOwnerOfProfile A boolean if the '_account' is an owner of the '_profileId' passed in function isOwnerOfProfile(bytes32 _profileId, address _owner) external view returns (bool isOwnerOfProfile); /// @dev Returns a boolean if the '_account' is a member of the '_profileId' passed in /// @param _profileId The 'profileId' to check if the '_account' is a member of /// @param _member The 'member' to check if they are a member of the '_profileId' passed in /// @return isMemberOfProfile A boolean if the '_account' is a member of the '_profileId' passed in function isMemberOfProfile(bytes32 _profileId, address _member) external view returns (bool isMemberOfProfile); /// ==================================== /// ==== External/Public Functions ===== /// ==================================== /// @dev Creates a new 'Profile' and returns the 'profileId' of the new profile /// /// Note: The 'name' and 'nonce' are used to generate the 'anchor' address /// /// Requirements: None, anyone can create a new profile /// /// @param _nonce The nonce to use to generate the 'anchor' address /// @param _name The name to use to generate the 'anchor' address /// @param _metadata The 'Metadata' to use to generate the 'anchor' address /// @param _owner The 'owner' to use to generate the 'anchor' address /// @param _members The 'members' to use to generate the 'anchor' address /// @return profileId The 'profileId' of the new profile function createProfile( uint256 _nonce, string memory _name, Metadata memory _metadata, address _owner, address[] memory _members ) external returns (bytes32 profileId); /// @dev Updates the 'name' of the '_profileId' passed in and returns the new 'anchor' address /// /// Requirements: Only the 'Profile' owner can update the name /// /// Note: The 'name' and 'nonce' are used to generate the 'anchor' address and this will update the 'anchor' /// so please use caution. You can always recreate your 'anchor' address by updating the name back /// to the original name used to create the profile. /// /// @param _profileId The 'profileId' to update the name for /// @param _name The new 'name' value /// @return anchor The new 'anchor' address function updateProfileName(bytes32 _profileId, string memory _name) external returns (address anchor); /// @dev Updates the 'Metadata' of the '_profileId' passed in /// /// Requirements: Only the 'Profile' owner can update the metadata /// /// @param _profileId The 'profileId' to update the metadata for /// @param _metadata The new 'Metadata' value function updateProfileMetadata(bytes32 _profileId, Metadata memory _metadata) external; /// @dev Updates the pending 'owner' of the '_profileId' passed in /// /// Requirements: Only the 'Profile' owner can update the pending owner /// /// @param _profileId The 'profileId' to update the pending owner for /// @param _pendingOwner The new pending 'owner' value function updateProfilePendingOwner(bytes32 _profileId, address _pendingOwner) external; /// @dev Accepts the pending 'owner' of the '_profileId' passed in /// /// Requirements: Only the pending owner can accept the ownership /// /// @param _profileId The 'profileId' to accept the ownership for function acceptProfileOwnership(bytes32 _profileId) external; /// @dev Adds members to the '_profileId' passed in /// /// Requirements: Only the 'Profile' owner can add members /// /// @param _profileId The 'profileId' to add members to /// @param _members The members to add to the '_profileId' passed in function addMembers(bytes32 _profileId, address[] memory _members) external; /// @dev Removes members from the '_profileId' passed in /// /// Requirements: Only the 'Profile' owner can remove members /// /// @param _profileId The 'profileId' to remove members from /// @param _members The members to remove from the '_profileId' passed in function removeMembers(bytes32 _profileId, address[] memory _members) external; /// @dev Recovers funds from the contract /// /// Requirements: Must be the Allo owner /// /// @param _token The token you want to use to recover funds /// @param _recipient The recipient of the recovered funds function recoverFunds(address _token, address _recipient) external; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.19; // Interfaces import {IAllo} from "./IAllo.sol"; // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⢿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⡟⠘⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣾⠻⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⡿⠀⠀⠸⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⢀⣠⣴⣴⣶⣶⣶⣦⣦⣀⡀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⡿⠃⠀⠙⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠁⠀⠀⠀⢻⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠘⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⠃⠀⠀⠀⠀⠈⢿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⣰⣿⣿⣿⡿⠋⠁⠀⠀⠈⠘⠹⣿⣿⣿⣿⣆⠀⠀⠀ // ⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡀⠀⠀ // ⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣟⠀⡀⢀⠀⡀⢀⠀⡀⢈⢿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⡇⠀⠀ // ⠀⠀⣠⣿⣿⣿⣿⣿⣿⡿⠋⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⡿⢿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣷⡀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠸⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠂⠀⠀ // ⠀⠀⠙⠛⠿⠻⠻⠛⠉⠀⠀⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣧⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⢻⣿⣿⣿⣷⣀⢀⠀⠀⠀⡀⣰⣾⣿⣿⣿⠏⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣧⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠹⢿⣿⣿⣿⣿⣾⣾⣷⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠃⠀⠀⠀⠀⠀⠀⠀⠀⠠⠿⠻⠟⠿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠟⠿⠟⠿⠆⠀⠸⠿⠿⠟⠯⠀⠀⠀⠸⠿⠿⠿⠏⠀⠀⠀⠀⠀⠈⠉⠻⠻⡿⣿⢿⡿⡿⠿⠛⠁⠀⠀⠀⠀⠀⠀ // allo.gitcoin.co /// @title IStrategy Interface /// @author @thelostone-mc <[email protected]>, @0xKurt <[email protected]>, @codenamejason <[email protected]>, @0xZakk <[email protected]>, @nfrgosselin <[email protected]> @0xZakk <[email protected]>, @nfrgosselin <[email protected]> /// @notice BaseStrategy is the base contract that all strategies should inherit from and uses this interface. interface IStrategy { /// ====================== /// ======= Storage ====== /// ====================== /// @notice The Status enum that all recipients are based from enum Status { None, Pending, Accepted, Rejected, Appealed, InReview, Canceled } /// @notice Payout summary struct to hold the payout data struct PayoutSummary { address recipientAddress; uint256 amount; } /// ====================== /// ======= Events ======= /// ====================== /// @notice Emitted when strategy is initialized. /// @param poolId The ID of the pool /// @param data The data passed to the 'initialize' function event Initialized(uint256 poolId, bytes data); /// @notice Emitted when a recipient is registered. /// @param recipientId The ID of the recipient /// @param data The data passed to the 'registerRecipient' function /// @param sender The sender event Registered(address indexed recipientId, bytes data, address sender); /// @notice Emitted when a recipient is allocated to. /// @param recipientId The ID of the recipient /// @param amount The amount allocated /// @param token The token allocated event Allocated(address indexed recipientId, uint256 amount, address token, address sender); /// @notice Emitted when tokens are distributed. /// @param recipientId The ID of the recipient /// @param recipientAddress The recipient /// @param amount The amount distributed /// @param sender The sender event Distributed(address indexed recipientId, address recipientAddress, uint256 amount, address sender); /// @notice Emitted when pool is set to active status. /// @param active The status of the pool event PoolActive(bool active); /// ====================== /// ======= Views ======== /// ====================== /// @notice Getter for the address of the Allo contract. /// @return The 'Allo' contract function getAllo() external view returns (IAllo); /// @notice Getter for the 'poolId' for this strategy. /// @return The ID of the pool function getPoolId() external view returns (uint256); /// @notice Getter for the 'id' of the strategy. /// @return The ID of the strategy function getStrategyId() external view returns (bytes32); /// @notice Checks whether a allocator is valid or not, will usually be true for all strategies /// and will depend on the strategy implementation. /// @param _allocator The allocator to check /// @return Whether the allocator is valid or not function isValidAllocator(address _allocator) external view returns (bool); /// @notice whether pool is active. /// @return Whether the pool is active or not function isPoolActive() external returns (bool); /// @notice Checks the amount of tokens in the pool. /// @return The balance of the pool function getPoolAmount() external view returns (uint256); /// @notice Increases the balance of the pool. /// @param _amount The amount to increase the pool by function increasePoolAmount(uint256 _amount) external; /// @notice Checks the status of a recipient probably tracked in a mapping, but will depend on the implementation /// for example, the OpenSelfRegistration only maps users to bool, and then assumes Accepted for those /// since there is no need for Pending or Rejected. /// @param _recipientId The ID of the recipient /// @return The status of the recipient function getRecipientStatus(address _recipientId) external view returns (Status); /// @notice Checks the amount allocated to a recipient for distribution. /// @dev Input the values you would send to distribute(), get the amounts each recipient in the array would receive. /// The encoded '_data' will be determined by the strategy, and will be used to determine the payout. /// @param _recipientIds The IDs of the recipients /// @param _data The encoded data function getPayouts(address[] memory _recipientIds, bytes[] memory _data) external view returns (PayoutSummary[] memory); /// ====================== /// ===== Functions ====== /// ====================== /// @notice /// @dev The default BaseStrategy version will not use the data if a strategy wants to use it, they will overwrite it, /// use it, and then call super.initialize(). /// @param _poolId The ID of the pool /// @param _data The encoded data function initialize(uint256 _poolId, bytes memory _data) external; /// @notice This will register a recipient, set their status (and any other strategy specific values), and /// return the ID of the recipient. /// @dev Able to change status all the way up to 'Accepted', or to 'Pending' and if there are more steps, additional /// functions should be added to allow the owner to check this. The owner could also check attestations directly /// and then accept for instance. The '_data' will be determined by the strategy implementation. /// @param _data The data to use to register the recipient /// @param _sender The address of the sender /// @return The ID of the recipient function registerRecipient(bytes memory _data, address _sender) external payable returns (address); /// @notice This will allocate to a recipient. /// @dev The encoded '_data' will be determined by the strategy implementation. /// @param _data The data to use to allocate to the recipient /// @param _sender The address of the sender function allocate(bytes memory _data, address _sender) external payable; /// @notice This will distribute funds (tokens) to recipients. /// @dev most strategies will track a TOTAL amount per recipient, and a PAID amount, and pay the difference /// this contract will need to track the amount paid already, so that it doesn't double pay. function distribute(address[] memory _recipientIds, bytes memory _data, address _sender) external; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⢿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⡟⠘⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣾⠻⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⡿⠀⠀⠸⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⢀⣠⣴⣴⣶⣶⣶⣦⣦⣀⡀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⡿⠃⠀⠙⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠁⠀⠀⠀⢻⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠘⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⠃⠀⠀⠀⠀⠈⢿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⣰⣿⣿⣿⡿⠋⠁⠀⠀⠈⠘⠹⣿⣿⣿⣿⣆⠀⠀⠀ // ⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡀⠀⠀ // ⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣟⠀⡀⢀⠀⡀⢀⠀⡀⢈⢿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⡇⠀⠀ // ⠀⠀⣠⣿⣿⣿⣿⣿⣿⡿⠋⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⡿⢿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣷⡀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠸⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠂⠀⠀ // ⠀⠀⠙⠛⠿⠻⠻⠛⠉⠀⠀⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣧⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⢻⣿⣿⣿⣷⣀⢀⠀⠀⠀⡀⣰⣾⣿⣿⣿⠏⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣧⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠹⢿⣿⣿⣿⣿⣾⣾⣷⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠃⠀⠀⠀⠀⠀⠀⠀⠀⠠⠿⠻⠟⠿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠟⠿⠟⠿⠆⠀⠸⠿⠿⠟⠯⠀⠀⠀⠸⠿⠿⠿⠏⠀⠀⠀⠀⠀⠈⠉⠻⠻⡿⣿⢿⡿⡿⠿⠛⠁⠀⠀⠀⠀⠀⠀ // allo.gitcoin.co /// @title Errors /// @author @thelostone-mc <[email protected]>, @KurtMerbeth <[email protected]>, @codenamejason <[email protected]> /// @notice Library containing all custom errors the protocol may revert with. contract Errors { /// ====================== /// ====== Generic ======= /// ====================== /// @notice Thrown as a general error when input / data is invalid error INVALID(); /// @notice Thrown when mismatch in decoding data error MISMATCH(); /// @notice Thrown when not enough funds are available error NOT_ENOUGH_FUNDS(); /// @notice Thrown when user is not authorized error UNAUTHORIZED(); /// @notice Thrown when address is the zero address error ZERO_ADDRESS(); /// @notice Thrown when the function is not implemented error NOT_IMPLEMENTED(); /// @notice Thrown when the value is non-zero error NON_ZERO_VALUE(); /// ====================== /// ====== Registry ====== /// ====================== /// @dev Thrown when the nonce passed has been used or not available error NONCE_NOT_AVAILABLE(); /// @dev Thrown when the 'msg.sender' is not the pending owner on ownership transfer error NOT_PENDING_OWNER(); /// @dev Thrown if the anchor creation fails error ANCHOR_ERROR(); /// ====================== /// ======== Allo ======== /// ====================== /// @notice Thrown when the strategy is not approved error NOT_APPROVED_STRATEGY(); /// @notice Thrown when the strategy is approved and should be cloned error IS_APPROVED_STRATEGY(); /// @notice Thrown when the fee is below 1e18 which is the fee percentage denominator error INVALID_FEE(); /// ====================== /// ===== IStrategy ====== /// ====================== /// @notice Thrown when data is already intialized error ALREADY_INITIALIZED(); /// @notice Thrown when data is yet to be initialized error NOT_INITIALIZED(); /// @notice Thrown when an invalid address is used error INVALID_ADDRESS(); /// @notice Thrown when a pool is inactive error POOL_INACTIVE(); /// @notice Thrown when a pool is already active error POOL_ACTIVE(); /// @notice Thrown when two arrays length are not equal error ARRAY_MISMATCH(); /// @notice Thrown when the registration is invalid. error INVALID_REGISTRATION(); /// @notice Thrown when the metadata is invalid. error INVALID_METADATA(); /// @notice Thrown when the recipient is not accepted. error RECIPIENT_NOT_ACCEPTED(); /// @notice Thrown when recipient is already accepted. error RECIPIENT_ALREADY_ACCEPTED(); /// @notice Thrown when registration is not active. error REGISTRATION_NOT_ACTIVE(); /// @notice Thrown when registration is active. error REGISTRATION_ACTIVE(); /// @notice Thrown when there is an error in recipient. error RECIPIENT_ERROR(address recipientId); /// @notice Thrown when the allocation is not active. error ALLOCATION_NOT_ACTIVE(); /// @notice Thrown when the allocation is not ended. error ALLOCATION_NOT_ENDED(); /// @notice Thrown when the allocation is active. error ALLOCATION_ACTIVE(); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⢿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⡟⠘⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣾⠻⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⡿⠀⠀⠸⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⢀⣠⣴⣴⣶⣶⣶⣦⣦⣀⡀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⡿⠃⠀⠙⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠁⠀⠀⠀⢻⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠘⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⠃⠀⠀⠀⠀⠈⢿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⣰⣿⣿⣿⡿⠋⠁⠀⠀⠈⠘⠹⣿⣿⣿⣿⣆⠀⠀⠀ // ⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡀⠀⠀ // ⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣟⠀⡀⢀⠀⡀⢀⠀⡀⢈⢿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⡇⠀⠀ // ⠀⠀⣠⣿⣿⣿⣿⣿⣿⡿⠋⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⡿⢿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣷⡀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠸⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠂⠀⠀ // ⠀⠀⠙⠛⠿⠻⠻⠛⠉⠀⠀⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣧⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⢻⣿⣿⣿⣷⣀⢀⠀⠀⠀⡀⣰⣾⣿⣿⣿⠏⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣧⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠹⢿⣿⣿⣿⣿⣾⣾⣷⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠃⠀⠀⠀⠀⠀⠀⠀⠀⠠⠿⠻⠟⠿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠟⠿⠟⠿⠆⠀⠸⠿⠿⠟⠯⠀⠀⠀⠸⠿⠿⠿⠏⠀⠀⠀⠀⠀⠈⠉⠻⠻⡿⣿⢿⡿⡿⠿⠛⠁⠀⠀⠀⠀⠀⠀ // allo.gitcoin.co /// @title Metadata /// @author @thelostone-mc <[email protected]>, @0xKurt <[email protected]>, @codenamejason <[email protected]>, @0xZakk <[email protected]>, @nfrgosselin <[email protected]> /// @notice Metadata is used to define the metadata for the protocol that is used throughout the system. struct Metadata { /// @notice Protocol ID corresponding to a specific protocol (currently using IPFS = 1) uint256 protocol; /// @notice Pointer (hash) to fetch metadata for the specified protocol string pointer; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⢿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⡟⠘⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣾⠻⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⡿⠀⠀⠸⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⢀⣠⣴⣴⣶⣶⣶⣦⣦⣀⡀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⡿⠃⠀⠙⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠁⠀⠀⠀⢻⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠘⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⠃⠀⠀⠀⠀⠈⢿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⣰⣿⣿⣿⡿⠋⠁⠀⠀⠈⠘⠹⣿⣿⣿⣿⣆⠀⠀⠀ // ⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡀⠀⠀ // ⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣟⠀⡀⢀⠀⡀⢀⠀⡀⢈⢿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⡇⠀⠀ // ⠀⠀⣠⣿⣿⣿⣿⣿⣿⡿⠋⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⡿⢿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣷⡀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠸⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠂⠀⠀ // ⠀⠀⠙⠛⠿⠻⠻⠛⠉⠀⠀⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣧⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⢻⣿⣿⣿⣷⣀⢀⠀⠀⠀⡀⣰⣾⣿⣿⣿⠏⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣧⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠹⢿⣿⣿⣿⣿⣾⣾⣷⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠃⠀⠀⠀⠀⠀⠀⠀⠀⠠⠿⠻⠟⠿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠟⠿⠟⠿⠆⠀⠸⠿⠿⠟⠯⠀⠀⠀⠸⠿⠿⠿⠏⠀⠀⠀⠀⠀⠈⠉⠻⠻⡿⣿⢿⡿⡿⠿⠛⠁⠀⠀⠀⠀⠀⠀ // allo.gitcoin.co /// @title Native token information /// @author @thelostone-mc <[email protected]>, @0xKurt <[email protected]>, @codenamejason <[email protected]>, @0xZakk <[email protected]>, @nfrgosselin <[email protected]> /// @notice This is used to define the address of the native token for the protocol contract Native { /// @notice Address of the native token address public constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity 0.8.19; // External Libraries import {SafeTransferLib} from "lib/solady/src/utils/SafeTransferLib.sol"; // Internal Libraries import "./Native.sol"; // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⢿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⡟⠘⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣾⠻⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⡿⠀⠀⠸⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⢀⣠⣴⣴⣶⣶⣶⣦⣦⣀⡀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⡿⠃⠀⠙⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠁⠀⠀⠀⢻⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠘⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⠃⠀⠀⠀⠀⠈⢿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⣰⣿⣿⣿⡿⠋⠁⠀⠀⠈⠘⠹⣿⣿⣿⣿⣆⠀⠀⠀ // ⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡀⠀⠀ // ⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣟⠀⡀⢀⠀⡀⢀⠀⡀⢈⢿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⡇⠀⠀ // ⠀⠀⣠⣿⣿⣿⣿⣿⣿⡿⠋⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⡿⢿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣷⡀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠸⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠂⠀⠀ // ⠀⠀⠙⠛⠿⠻⠻⠛⠉⠀⠀⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣧⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⢻⣿⣿⣿⣷⣀⢀⠀⠀⠀⡀⣰⣾⣿⣿⣿⠏⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣧⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠹⢿⣿⣿⣿⣿⣾⣾⣷⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠃⠀⠀⠀⠀⠀⠀⠀⠀⠠⠿⠻⠟⠿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠟⠿⠟⠿⠆⠀⠸⠿⠿⠟⠯⠀⠀⠀⠸⠿⠿⠿⠏⠀⠀⠀⠀⠀⠈⠉⠻⠻⡿⣿⢿⡿⡿⠿⠛⠁⠀⠀⠀⠀⠀⠀ // allo.gitcoin.co /// @title Transfer contract /// @author @thelostone-mc <[email protected]>, @0xKurt <[email protected]>, @codenamejason <[email protected]>, @0xZakk <[email protected]>, @nfrgosselin <[email protected]> /// @notice A helper contract to transfer tokens within Allo protocol /// @dev Handles the transfer of tokens to an address contract Transfer is Native { /// @notice Thrown when the amount of tokens sent does not match the amount of tokens expected error AMOUNT_MISMATCH(); /// @notice This holds the details for a transfer struct TransferData { address from; address to; uint256 amount; } /// @notice Transfer an amount of a token to an array of addresses /// @param _token The address of the token /// @param _transferData TransferData[] /// @return Whether the transfer was successful or not function _transferAmountsFrom(address _token, TransferData[] memory _transferData) internal virtual returns (bool) { uint256 msgValue = msg.value; for (uint256 i; i < _transferData.length;) { TransferData memory transferData = _transferData[i]; if (_token == NATIVE) { msgValue -= transferData.amount; SafeTransferLib.safeTransferETH(transferData.to, transferData.amount); } else { SafeTransferLib.safeTransferFrom(_token, transferData.from, transferData.to, transferData.amount); } unchecked { i++; } } if (msgValue != 0) revert AMOUNT_MISMATCH(); return true; } /// @notice Transfer an amount of a token to an address /// @param _token The address of the token /// @param _transferData Individual TransferData /// @return Whether the transfer was successful or not function _transferAmountFrom(address _token, TransferData memory _transferData) internal virtual returns (bool) { uint256 amount = _transferData.amount; if (_token == NATIVE) { // Native Token if (msg.value < amount) revert AMOUNT_MISMATCH(); SafeTransferLib.safeTransferETH(_transferData.to, amount); } else { SafeTransferLib.safeTransferFrom(_token, _transferData.from, _transferData.to, amount); } return true; } /// @notice Transfer an amount of a token to an address /// @param _token The token to transfer /// @param _to The address to transfer to /// @param _amount The amount to transfer function _transferAmount(address _token, address _to, uint256 _amount) internal virtual { if (_token == NATIVE) { SafeTransferLib.safeTransferETH(_to, _amount); } else { SafeTransferLib.safeTransfer(_token, _to, _amount); } } /// @notice Get the balance of a token for an account /// @param _token The token to get the balance of /// @param _account The account to get the balance for /// @return The balance of the token for the account function _getBalance(address _token, address _account) internal view returns (uint256) { if (_token == NATIVE) { return payable(_account).balance; } else { return SafeTransferLib.balanceOf(_token, _account); } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.19; // Interfaces import "../core/interfaces/IStrategy.sol"; // Libraries import {Transfer} from "../core/libraries/Transfer.sol"; import {Errors} from "../core/libraries/Errors.sol"; // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⢿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⡟⠘⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣾⣿⣿⣿⣿⣾⠻⣿⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⡿⠀⠀⠸⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠀⠀⢀⣠⣴⣴⣶⣶⣶⣦⣦⣀⡀⠀⠀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⡿⠃⠀⠙⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠁⠀⠀⠀⢻⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠘⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⠃⠀⠀⠀⠀⠈⢿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⣰⣿⣿⣿⡿⠋⠁⠀⠀⠈⠘⠹⣿⣿⣿⣿⣆⠀⠀⠀ // ⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠈⢿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣾⣿⣿⣿⠏⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⡀⠀⠀ // ⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣟⠀⡀⢀⠀⡀⢀⠀⡀⢈⢿⡟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⡇⠀⠀ // ⠀⠀⣠⣿⣿⣿⣿⣿⣿⡿⠋⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⡿⢿⠿⠿⠿⠿⠿⠿⠿⠿⠿⢿⣿⣿⣿⣷⡀⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠸⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⠂⠀⠀ // ⠀⠀⠙⠛⠿⠻⠻⠛⠉⠀⠀⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣿⣿⣿⣧⠀⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⢻⣿⣿⣿⣷⣀⢀⠀⠀⠀⡀⣰⣾⣿⣿⣿⠏⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣧⠀⠀⢸⣿⣿⣿⣗⠀⠀⠀⢸⣿⣿⣿⡯⠀⠀⠀⠀⠹⢿⣿⣿⣿⣿⣾⣾⣷⣿⣿⣿⣿⡿⠋⠀⠀⠀⠀ // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠙⠋⠛⠙⠋⠛⠙⠋⠛⠙⠋⠃⠀⠀⠀⠀⠀⠀⠀⠀⠠⠿⠻⠟⠿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠟⠿⠟⠿⠆⠀⠸⠿⠿⠟⠯⠀⠀⠀⠸⠿⠿⠿⠏⠀⠀⠀⠀⠀⠈⠉⠻⠻⡿⣿⢿⡿⡿⠿⠛⠁⠀⠀⠀⠀⠀⠀ // allo.gitcoin.co /// @title BaseStrategy Contract /// @author @thelostone-mc <[email protected]>, @0xKurt <[email protected]>, @codenamejason <[email protected]>, @0xZakk <[email protected]>, @nfrgosselin <[email protected]> /// @notice This contract is the base contract for all strategies /// @dev This contract is implemented by all strategies. abstract contract BaseStrategy is IStrategy, Transfer, Errors { /// ========================== /// === Storage Variables ==== /// ========================== IAllo internal immutable allo; bytes32 internal immutable strategyId; bool internal poolActive; uint256 internal poolId; uint256 internal poolAmount; /// ==================================== /// ========== Constructor ============= /// ==================================== /// @notice Constructor to set the Allo contract and "strategyId'. /// @param _allo Address of the Allo contract. /// @param _name Name of the strategy constructor(address _allo, string memory _name) { allo = IAllo(_allo); strategyId = keccak256(abi.encode(_name)); } /// ==================================== /// =========== Modifiers ============== /// ==================================== /// @notice Modifier to check if the 'msg.sender' is the Allo contract. /// @dev Reverts if the 'msg.sender' is not the Allo contract. modifier onlyAllo() { _checkOnlyAllo(); _; } /// @notice Modifier to check if the '_sender' is a pool manager. /// @dev Reverts if the '_sender' is not a pool manager. /// @param _sender The address to check if they are a pool manager modifier onlyPoolManager(address _sender) { _checkOnlyPoolManager(_sender); _; } /// @notice Modifier to check if the pool is active. /// @dev Reverts if the pool is not active. modifier onlyActivePool() { _checkOnlyActivePool(); _; } /// @notice Modifier to check if the pool is inactive. /// @dev Reverts if the pool is active. modifier onlyInactivePool() { _checkInactivePool(); _; } /// @notice Modifier to check if the pool is initialized. /// @dev Reverts if the pool is not initialized. modifier onlyInitialized() { _checkOnlyInitialized(); _; } /// ================================ /// =========== Views ============== /// ================================ /// @notice Getter for the 'Allo' contract. /// @return The Allo contract function getAllo() external view override returns (IAllo) { return allo; } /// @notice Getter for the 'poolId'. /// @return The ID of the pool function getPoolId() external view override returns (uint256) { return poolId; } /// @notice Getter for the 'strategyId'. /// @return The ID of the strategy function getStrategyId() external view override returns (bytes32) { return strategyId; } /// @notice Getter for the 'poolAmount'. /// @return The balance of the pool function getPoolAmount() external view virtual override returns (uint256) { return poolAmount; } /// @notice Getter for whether or not the pool is active. /// @return 'true' if the pool is active, otherwise 'false' function isPoolActive() external view override returns (bool) { return _isPoolActive(); } /// @notice Getter for the status of a recipient. /// @param _recipientId The ID of the recipient /// @return The status of the recipient function getRecipientStatus(address _recipientId) external view virtual returns (Status) { return _getRecipientStatus(_recipientId); } /// ==================================== /// =========== Functions ============== /// ==================================== /// @notice Initializes the 'Basetrategy'. /// @dev Will revert if the poolId is invalid or already initialized /// @param _poolId ID of the pool function __BaseStrategy_init(uint256 _poolId) internal virtual onlyAllo { // check if pool ID is not initialized already, if it is, revert if (poolId != 0) revert ALREADY_INITIALIZED(); // check if pool ID is valid and not zero (0), if it is, revert if (_poolId == 0) revert INVALID(); poolId = _poolId; } /// @notice Increases the pool amount. /// @dev Increases the 'poolAmount' by '_amount'. Only 'Allo' contract can call this. /// @param _amount The amount to increase the pool by function increasePoolAmount(uint256 _amount) external override onlyAllo { _beforeIncreasePoolAmount(_amount); poolAmount += _amount; _afterIncreasePoolAmount(_amount); } /// @notice Registers a recipient. /// @dev Registers a recipient and returns the ID of the recipient. The encoded '_data' will be determined by the /// strategy implementation. Only 'Allo' contract can call this when it is initialized. /// @param _data The data to use to register the recipient /// @param _sender The address of the sender /// @return recipientId The recipientId function registerRecipient(bytes memory _data, address _sender) external payable onlyAllo onlyInitialized returns (address recipientId) { _beforeRegisterRecipient(_data, _sender); recipientId = _registerRecipient(_data, _sender); _afterRegisterRecipient(_data, _sender); } /// @notice Allocates to a recipient. /// @dev The encoded '_data' will be determined by the strategy implementation. Only 'Allo' contract can /// call this when it is initialized. /// @param _data The data to use to allocate to the recipient /// @param _sender The address of the sender function allocate(bytes memory _data, address _sender) external payable onlyAllo onlyInitialized { _beforeAllocate(_data, _sender); _allocate(_data, _sender); _afterAllocate(_data, _sender); } /// @notice Distributes funds (tokens) to recipients. /// @dev The encoded '_data' will be determined by the strategy implementation. Only 'Allo' contract can /// call this when it is initialized. /// @param _recipientIds The IDs of the recipients /// @param _data The data to use to distribute to the recipients /// @param _sender The address of the sender function distribute(address[] memory _recipientIds, bytes memory _data, address _sender) external onlyAllo onlyInitialized { _beforeDistribute(_recipientIds, _data, _sender); _distribute(_recipientIds, _data, _sender); _afterDistribute(_recipientIds, _data, _sender); } /// @notice Gets the payout summary for recipients. /// @dev The encoded '_data' will be determined by the strategy implementation. /// @param _recipientIds The IDs of the recipients /// @param _data The data to use to get the payout summary for the recipients /// @return The payout summary for the recipients function getPayouts(address[] memory _recipientIds, bytes[] memory _data) external view virtual override returns (PayoutSummary[] memory) { uint256 recipientLength = _recipientIds.length; // check if the length of the recipient IDs and data arrays are equal, if they are not, revert if (recipientLength != _data.length) revert ARRAY_MISMATCH(); PayoutSummary[] memory payouts = new PayoutSummary[](recipientLength); for (uint256 i; i < recipientLength;) { payouts[i] = _getPayout(_recipientIds[i], _data[i]); unchecked { i++; } } return payouts; } /// @notice Checks if the '_allocator' is a valid allocator. /// @dev How the allocator is determined is up to the strategy implementation. /// @param _allocator The address to check if it is a valid allocator for the strategy. /// @return 'true' if the address is a valid allocator, 'false' otherwise function isValidAllocator(address _allocator) external view virtual override returns (bool) { return _isValidAllocator(_allocator); } /// ==================================== /// ============ Internal ============== /// ==================================== /// @notice Checks if the 'msg.sender' is the Allo contract. /// @dev Reverts if the 'msg.sender' is not the Allo contract. function _checkOnlyAllo() internal view { if (msg.sender != address(allo)) revert UNAUTHORIZED(); } /// @notice Checks if the '_sender' is a pool manager. /// @dev Reverts if the '_sender' is not a pool manager. /// @param _sender The address to check if they are a pool manager function _checkOnlyPoolManager(address _sender) internal view { if (!allo.isPoolManager(poolId, _sender)) revert UNAUTHORIZED(); } /// @notice Checks if the pool is active. /// @dev Reverts if the pool is not active. function _checkOnlyActivePool() internal view { if (!poolActive) revert POOL_INACTIVE(); } /// @notice Checks if the pool is inactive. /// @dev Reverts if the pool is active. function _checkInactivePool() internal view { if (poolActive) revert POOL_ACTIVE(); } /// @notice Checks if the pool is initialized. /// @dev Reverts if the pool is not initialized. function _checkOnlyInitialized() internal view { if (poolId == 0) revert NOT_INITIALIZED(); } /// @notice Set the pool to active or inactive status. /// @dev This will emit a 'PoolActive()' event. Used by the strategy implementation. /// @param _active The status to set, 'true' means active, 'false' means inactive function _setPoolActive(bool _active) internal { poolActive = _active; emit PoolActive(_active); } /// @notice Checks if the pool is active. /// @dev Used by the strategy implementation. /// @return 'true' if the pool is active, otherwise 'false' function _isPoolActive() internal view virtual returns (bool) { return poolActive; } /// @notice Checks if the allocator is valid /// @param _allocator The allocator address /// @return 'true' if the allocator is valid, otherwise 'false' function _isValidAllocator(address _allocator) internal view virtual returns (bool); /// @notice This will register a recipient, set their status (and any other strategy specific values), and /// return the ID of the recipient. /// @dev Able to change status all the way up to Accepted, or to Pending and if there are more steps, additional /// functions should be added to allow the owner to check this. The owner could also check attestations directly /// and then Accept for instance. /// @param _data The data to use to register the recipient /// @param _sender The address of the sender /// @return The ID of the recipient function _registerRecipient(bytes memory _data, address _sender) internal virtual returns (address); /// @notice This will allocate to a recipient. /// @dev The encoded '_data' will be determined by the strategy implementation. /// @param _data The data to use to allocate to the recipient /// @param _sender The address of the sender function _allocate(bytes memory _data, address _sender) internal virtual; /// @notice This will distribute funds (tokens) to recipients. /// @dev most strategies will track a TOTAL amount per recipient, and a PAID amount, and pay the difference /// this contract will need to track the amount paid already, so that it doesn't double pay. /// @param _recipientIds The ids of the recipients to distribute to /// @param _data Data required will depend on the strategy implementation /// @param _sender The address of the sender function _distribute(address[] memory _recipientIds, bytes memory _data, address _sender) internal virtual; /// @notice This will get the payout summary for a recipient. /// @dev The encoded '_data' will be determined by the strategy implementation. /// @param _recipientId The ID of the recipient /// @param _data The data to use to get the payout summary for the recipient /// @return The payout summary for the recipient function _getPayout(address _recipientId, bytes memory _data) internal view virtual returns (PayoutSummary memory); /// @notice This will get the status of a recipient. /// @param _recipientId The ID of the recipient /// @return The status of the recipient function _getRecipientStatus(address _recipientId) internal view virtual returns (Status); /// =================================== /// ============== Hooks ============== /// =================================== /// @notice Hook called before increasing the pool amount. /// @param _amount The amount to increase the pool by function _beforeIncreasePoolAmount(uint256 _amount) internal virtual {} /// @notice Hook called after increasing the pool amount. /// @param _amount The amount to increase the pool by function _afterIncreasePoolAmount(uint256 _amount) internal virtual {} /// @notice Hook called before registering a recipient. /// @param _data The data to use to register the recipient /// @param _sender The address of the sender function _beforeRegisterRecipient(bytes memory _data, address _sender) internal virtual {} /// @notice Hook called after registering a recipient. /// @param _data The data to use to register the recipient /// @param _sender The address of the sender function _afterRegisterRecipient(bytes memory _data, address _sender) internal virtual {} /// @notice Hook called before allocating to a recipient. /// @param _data The data to use to allocate to the recipient /// @param _sender The address of the sender function _beforeAllocate(bytes memory _data, address _sender) internal virtual {} /// @notice Hook called after allocating to a recipient. /// @param _data The data to use to allocate to the recipient /// @param _sender The address of the sender function _afterAllocate(bytes memory _data, address _sender) internal virtual {} /// @notice Hook called before distributing funds (tokens) to recipients. /// @param _recipientIds The IDs of the recipients /// @param _data The data to use to distribute to the recipients /// @param _sender The address of the sender function _beforeDistribute(address[] memory _recipientIds, bytes memory _data, address _sender) internal virtual {} /// @notice Hook called after distributing funds (tokens) to recipients. /// @param _recipientIds The IDs of the recipients /// @param _data The data to use to distribute to the recipients /// @param _sender The address of the sender function _afterDistribute(address[] memory _recipientIds, bytes memory _data, address _sender) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Multicall.sol) pragma solidity ^0.8.0; import "./Address.sol"; /** * @dev Provides a function to batch together multiple calls in a single external call. * * _Available since v4.1._ */ abstract contract Multicall { /** * @dev Receives and executes a batch of function calls on this contract. * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { results[i] = Address.functionDelegateCall(address(this), data[i]); } return results; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// /// @dev Note: /// - For ETH transfers, please use `forceSafeTransferETH` for gas griefing protection. /// - For ERC20s, this implementation won't check that a token has code, /// responsibility is delegated to the caller. library SafeTransferLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ETH transfer has failed. error ETHTransferFailed(); /// @dev The ERC20 `transferFrom` has failed. error TransferFromFailed(); /// @dev The ERC20 `transfer` has failed. error TransferFailed(); /// @dev The ERC20 `approve` has failed. error ApproveFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Suggested gas stipend for contract receiving ETH /// that disallows any storage writes. uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300; /// @dev Suggested gas stipend for contract receiving ETH to perform a few /// storage reads and writes, but low enough to prevent griefing. /// Multiply by a small constant (e.g. 2), if needed. uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ETH OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` (in wei) ETH to `to`. /// Reverts upon failure. /// /// Note: This implementation does NOT protect against gas griefing. /// Please use `forceSafeTransferETH` for gas griefing protection. function safeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { // Transfer the ETH and check if it succeeded or not. if iszero(call(gas(), to, amount, 0x00, 0x00, 0x00, 0x00)) { // Store the function selector of `ETHTransferFailed()`. mstore(0x00, 0xb12d13eb) // Revert with (offset, size). revert(0x1c, 0x04) } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`. /// The `gasStipend` can be set to a low enough value to prevent /// storage writes or gas griefing. /// /// If sending via the normal procedure fails, force sends the ETH by /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH. /// /// Reverts if the current contract has insufficient balance. function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { // If insufficient balance, revert. if lt(selfbalance(), amount) { // Store the function selector of `ETHTransferFailed()`. mstore(0x00, 0xb12d13eb) // Revert with (offset, size). revert(0x1c, 0x04) } // Transfer the ETH and check if it succeeded or not. if iszero(call(gasStipend, to, amount, 0x00, 0x00, 0x00, 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. // We can directly use `SELFDESTRUCT` in the contract creation. // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758 if iszero(create(amount, 0x0b, 0x16)) { // To coerce gas estimation to provide enough gas for the `create` above. if iszero(gt(gas(), 1000000)) { revert(0x00, 0x00) } } } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a gas stipend /// equal to `GAS_STIPEND_NO_GRIEF`. This gas stipend is a reasonable default /// for 99% of cases and can be overridden with the three-argument version of this /// function if necessary. /// /// If sending via the normal procedure fails, force sends the ETH by /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH. /// /// Reverts if the current contract has insufficient balance. function forceSafeTransferETH(address to, uint256 amount) internal { // Manually inlined because the compiler doesn't inline functions with branches. /// @solidity memory-safe-assembly assembly { // If insufficient balance, revert. if lt(selfbalance(), amount) { // Store the function selector of `ETHTransferFailed()`. mstore(0x00, 0xb12d13eb) // Revert with (offset, size). revert(0x1c, 0x04) } // Transfer the ETH and check if it succeeded or not. if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, 0x00, 0x00, 0x00, 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. // We can directly use `SELFDESTRUCT` in the contract creation. // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758 if iszero(create(amount, 0x0b, 0x16)) { // To coerce gas estimation to provide enough gas for the `create` above. if iszero(gt(gas(), 1000000)) { revert(0x00, 0x00) } } } } } /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`. /// The `gasStipend` can be set to a low enough value to prevent /// storage writes or gas griefing. /// /// Simply use `gasleft()` for `gasStipend` if you don't need a gas stipend. /// /// Note: Does NOT revert upon failure. /// Returns whether the transfer of ETH is successful instead. function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { // Transfer the ETH and check if it succeeded or not. success := call(gasStipend, to, amount, 0x00, 0x00, 0x00, 0x00) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for /// the current contract to manage. function safeTransferFrom(address token, address from, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x60, amount) // Store the `amount` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. // Store the function selector of `transferFrom(address,address,uint256)`. mstore(0x0c, 0x23b872dd000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { // Store the function selector of `TransferFromFailed()`. mstore(0x00, 0x7939f424) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends all of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have their entire balance approved for /// the current contract to manage. function safeTransferAllFrom(address token, address from, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. // Store the function selector of `balanceOf(address)`. mstore(0x0c, 0x70a08231000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20) ) ) { // Store the function selector of `TransferFromFailed()`. mstore(0x00, 0x7939f424) // Revert with (offset, size). revert(0x1c, 0x04) } // Store the function selector of `transferFrom(address,address,uint256)`. mstore(0x00, 0x23b872dd) // The `amount` is already at 0x60. Load it for the function's return value. amount := mload(0x60) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { // Store the function selector of `TransferFromFailed()`. mstore(0x00, 0x7939f424) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransfer(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. // Store the function selector of `transfer(address,uint256)`. mstore(0x00, 0xa9059cbb000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the part of the free memory pointer that was overwritten. mstore(0x34, 0) } } /// @dev Sends all of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransferAll(address token, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, address()) // Store the address of the current contract. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x14, to) // Store the `to` argument. // The `amount` is already at 0x34. Load it for the function's return value. amount := mload(0x34) // Store the function selector of `transfer(address,uint256)`. mstore(0x00, 0xa9059cbb000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the part of the free memory pointer that was overwritten. mstore(0x34, 0) } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// Reverts upon failure. function safeApprove(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. // Store the function selector of `approve(address,uint256)`. mstore(0x00, 0x095ea7b3000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `ApproveFailed()`. mstore(0x00, 0x3e3f8f73) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the part of the free memory pointer that was overwritten. mstore(0x34, 0) } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// If the initial attempt to approve fails, attempts to reset the approved amount to zero, /// then retries the approval again (some tokens, e.g. USDT, requires this). /// Reverts upon failure. function safeApproveWithRetry(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. // Store the function selector of `approve(address,uint256)`. mstore(0x00, 0x095ea7b3000000000000000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x34, 0) // Store 0 for the `amount`. mstore(0x00, 0x095ea7b3000000000000000000000000) // Store the function selector. // We can ignore the result of this call. Just need to check the next call. pop(call(gas(), token, 0, 0x10, 0x44, 0x00, 0x00)) mstore(0x34, amount) // Store back the original `amount`. if iszero( and( or(eq(mload(0x00), 1), iszero(returndatasize())), call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `ApproveFailed()`. mstore(0x00, 0x3e3f8f73) // Revert with (offset, size). revert(0x1c, 0x04) } } // Restore the part of the free memory pointer that was overwritten. mstore(0x34, 0) } } /// @dev Returns the amount of ERC20 `token` owned by `account`. /// Returns zero if the `token` does not exist. function balanceOf(address token, address account) internal view returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x14, account) // Store the `account` argument. // Store the function selector of `balanceOf(address)`. mstore(0x00, 0x70a08231000000000000000000000000) amount := mul( mload(0x20), and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20) ) ) } } }
{ "optimizer": { "enabled": true, "runs": 400 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_allo","type":"address"},{"internalType":"string","name":"_name","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ALLOCATION_ACTIVE","type":"error"},{"inputs":[],"name":"ALLOCATION_NOT_ACTIVE","type":"error"},{"inputs":[],"name":"ALLOCATION_NOT_ENDED","type":"error"},{"inputs":[],"name":"ALREADY_INITIALIZED","type":"error"},{"inputs":[],"name":"AMOUNT_MISMATCH","type":"error"},{"inputs":[],"name":"ANCHOR_ERROR","type":"error"},{"inputs":[],"name":"ARRAY_MISMATCH","type":"error"},{"inputs":[],"name":"INVALID","type":"error"},{"inputs":[],"name":"INVALID_ADDRESS","type":"error"},{"inputs":[],"name":"INVALID_FEE","type":"error"},{"inputs":[],"name":"INVALID_METADATA","type":"error"},{"inputs":[],"name":"INVALID_REGISTRATION","type":"error"},{"inputs":[],"name":"IS_APPROVED_STRATEGY","type":"error"},{"inputs":[],"name":"MISMATCH","type":"error"},{"inputs":[],"name":"NONCE_NOT_AVAILABLE","type":"error"},{"inputs":[],"name":"NON_ZERO_VALUE","type":"error"},{"inputs":[],"name":"NOT_APPROVED_STRATEGY","type":"error"},{"inputs":[],"name":"NOT_ENOUGH_FUNDS","type":"error"},{"inputs":[],"name":"NOT_IMPLEMENTED","type":"error"},{"inputs":[],"name":"NOT_INITIALIZED","type":"error"},{"inputs":[],"name":"NOT_PENDING_OWNER","type":"error"},{"inputs":[],"name":"POOL_ACTIVE","type":"error"},{"inputs":[],"name":"POOL_INACTIVE","type":"error"},{"inputs":[],"name":"RECIPIENT_ALREADY_ACCEPTED","type":"error"},{"inputs":[{"internalType":"address","name":"recipientId","type":"address"}],"name":"RECIPIENT_ERROR","type":"error"},{"inputs":[],"name":"RECIPIENT_NOT_ACCEPTED","type":"error"},{"inputs":[],"name":"REGISTRATION_ACTIVE","type":"error"},{"inputs":[],"name":"REGISTRATION_NOT_ACTIVE","type":"error"},{"inputs":[],"name":"UNAUTHORIZED","type":"error"},{"inputs":[],"name":"ZERO_ADDRESS","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipientId","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"Allocated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipientId","type":"address"},{"indexed":false,"internalType":"address","name":"recipientAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"Distributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"poolId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"active","type":"bool"}],"name":"PoolActive","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"rowIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fullRow","type":"uint256"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"RecipientStatusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipientId","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"Registered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"registrationStartTime","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"registrationEndTime","type":"uint64"},{"indexed":false,"internalType":"address","name":"sender","type":"address"}],"name":"TimestampsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipientId","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint8","name":"status","type":"uint8"}],"name":"UpdatedRegistration","type":"event"},{"inputs":[],"name":"NATIVE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"}],"name":"allocate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_recipientIds","type":"address[]"},{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"}],"name":"distribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllo","outputs":[{"internalType":"contract IAllo","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_recipientIds","type":"address[]"},{"internalType":"bytes[]","name":"_data","type":"bytes[]"}],"name":"getPayouts","outputs":[{"components":[{"internalType":"address","name":"recipientAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IStrategy.PayoutSummary[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipientId","type":"address"}],"name":"getRecipient","outputs":[{"components":[{"internalType":"bool","name":"useRegistryAnchor","type":"bool"},{"internalType":"address","name":"recipientAddress","type":"address"},{"components":[{"internalType":"uint256","name":"protocol","type":"uint256"},{"internalType":"string","name":"pointer","type":"string"}],"internalType":"struct Metadata","name":"metadata","type":"tuple"}],"internalType":"struct DirectGrantsLiteStrategy.Recipient","name":"recipient","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipientId","type":"address"}],"name":"getRecipientStatus","outputs":[{"internalType":"enum IStrategy.Status","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStrategyId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"increasePoolAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_poolId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPoolActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_allocator","type":"address"}],"name":"isValidAllocator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataRequired","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"recipientToStatusIndexes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"recipientsCounter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"}],"name":"registerRecipient","outputs":[{"internalType":"address","name":"recipientId","type":"address"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"registrationEndTime","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registrationStartTime","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"statusRow","type":"uint256"}],"internalType":"struct DirectGrantsLiteStrategy.ApplicationStatus[]","name":"statuses","type":"tuple[]"},{"internalType":"uint256","name":"refRecipientsCounter","type":"uint256"}],"name":"reviewRecipients","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"statusesBitMap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"_registrationStartTime","type":"uint64"},{"internalType":"uint64","name":"_registrationEndTime","type":"uint64"}],"name":"updatePoolTimestamps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"useRegistryAnchor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60c06040523480156200001157600080fd5b5060405162002b2e38038062002b2e8339810160408190526200003491620000ba565b6001600160a01b038216608052604051829082906200005890829060200162000195565b60408051601f19818403018152919052805160209091012060a05250620001ca92505050565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620000b157818101518382015260200162000097565b50506000910152565b60008060408385031215620000ce57600080fd5b82516001600160a01b0381168114620000e657600080fd5b60208401519092506001600160401b03808211156200010457600080fd5b818501915085601f8301126200011957600080fd5b8151818111156200012e576200012e6200007e565b604051601f8201601f19908116603f011681019083821181831017156200015957620001596200007e565b816040528281528860208487010111156200017357600080fd5b6200018683602083016020880162000094565b80955050505050509250929050565b6020815260008251806020840152620001b681604085016020870162000094565b601f01601f19169190910160400192915050565b60805160a0516129226200020c60003960006102970152600081816102280152818161059001528181610e7201528181610f24015261124701526129226000f3fe6080604052600436106101a55760003560e01c80639af5c09d116100e1578063dff7d2c71161008a578063ef2920fc11610064578063ef2920fc14610505578063f31db3d114610518578063f5b0dfb714610538578063f6f258911461055857600080fd5b8063dff7d2c714610491578063eb11af93146104b8578063edd146cc146104e557600080fd5b8063b2b878d0116100bb578063b2b878d014610430578063cb0e85a61461045d578063df868ed31461047c57600080fd5b80639af5c09d1461039d578063a0cf0aea146103db578063ac9650d81461040357600080fd5b80634ab4ba421161014e5780635708973911610128578063570897391461032057806362812a391461033a57806375777aaa1461036757806395355b3b1461038757600080fd5b80634ab4ba42146102bb5780634d31d087146102d057806351cff8d91461030057600080fd5b80632bbe0cae1161017f5780632bbe0cae1461026057806338fff2d01461027357806342fda9c71461028857600080fd5b806301fc1c64146101b95780630a6f0ee9146101f957806315cc481e1461021957600080fd5b366101b4576101b2610585565b005b600080fd5b3480156101c557600080fd5b506101e66101d4366004611b61565b60076020526000908152604090205481565b6040519081526020015b60405180910390f35b34801561020557600080fd5b506101b2610214366004611d46565b6105d0565b34801561022557600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b0390911681526020016101f0565b61024861026e366004611dbd565b6105f0565b34801561027f57600080fd5b506001546101e6565b34801561029457600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006101e6565b3480156102c757600080fd5b506002546101e6565b3480156102dc57600080fd5b506102f06102eb366004611b61565b610615565b60405190151581526020016101f0565b34801561030c57600080fd5b506101b261031b366004611b61565b610620565b34801561032c57600080fd5b506003546102f09060ff1681565b34801561034657600080fd5b5061035a610355366004611b61565b61064a565b6040516101f09190611e5e565b34801561037357600080fd5b506101b2610382366004611ec2565b61065b565b34801561039357600080fd5b506101e660045481565b3480156103a957600080fd5b506003546103c3906201000090046001600160401b031681565b6040516001600160401b0390911681526020016101f0565b3480156103e757600080fd5b5061024873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561040f57600080fd5b5061042361041e366004611ef0565b61070d565b6040516101f09190611f64565b34801561043c57600080fd5b5061045061044b366004611fc6565b610801565b6040516101f0919061209a565b34801561046957600080fd5b506003546102f090610100900460ff1681565b34801561048857600080fd5b506102f06108ff565b34801561049d57600080fd5b506003546103c390600160501b90046001600160401b031681565b3480156104c457600080fd5b506104d86104d3366004611b61565b61090e565b6040516101f09190612108565b3480156104f157600080fd5b506101b2610500366004612130565b610919565b6101b2610513366004611dbd565b610974565b34801561052457600080fd5b506101b2610533366004612176565b610992565b34801561054457600080fd5b506101b2610553366004612230565b610a70565b34801561056457600080fd5b506101e6610573366004612230565b60066020526000908152604090205481565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105ce5760405163075fd2b160e01b815260040160405180910390fd5b565b6105d8610585565b6105e0610a9a565b6105eb838383610abd565b505050565b60006105fa610585565b610602610a9a565b61060c8383610ad6565b90505b92915050565b600061060f82610e55565b3361062a81610efa565b60006106368330610fac565b905080610644843383610ff5565b50505050565b610652611b06565b61060f8261102f565b3361066581610efa565b61066f8383611128565b6003805471ffffffffffffffffffffffffffffffff00001916620100006001600160401b03868116820267ffffffffffffffff60501b191692909217600160501b8684168102919091179384905560408051928504841683529304909116602082015233918101919091527f70d34c8836b996cffd8970ba5edf940d83ca7c8f30f738ea4fd8566a37d93359906060015b60405180910390a1505050565b6060816001600160401b0381111561072757610727611b85565b60405190808252806020026020018201604052801561075a57816020015b60608152602001906001900390816107455790505b50905060005b828110156107fa576107ca3085858481811061077e5761077e612249565b9050602002810190610790919061225f565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061115b92505050565b8282815181106107dc576107dc612249565b602002602001018190525080806107f2906122c2565b915050610760565b5092915050565b8151815160609190811461082857604051633da4c02b60e11b815260040160405180910390fd5b6000816001600160401b0381111561084257610842611b85565b60405190808252806020026020018201604052801561088757816020015b60408051808201909152600080825260208201528152602001906001900390816108605790505b50905060005b828110156108f6576108d18682815181106108aa576108aa612249565b60200260200101518683815181106108c4576108c4612249565b6020026020010151611180565b8282815181106108e3576108e3612249565b602090810291909101015260010161088d565b50949350505050565b6000610909611199565b905090565b600061060f826111e1565b610921610585565b60008180602001905181019061093791906122f0565b90506109438382611200565b7f91efa3d50feccde0d0d202f8ae5c41ca0b2be614cebcb2bd2f4b019396e6568a8383604051610700929190612370565b61097c610585565b610984610a9a565b61098e82826113a9565b5050565b3361099c81610efa565b60045482146109be57604051637fcce2a960e01b815260040160405180910390fd5b825160005b81811015610a695760008582815181106109df576109df612249565b60200260200101516000015190506000868381518110610a0157610a01612249565b6020908102919091018101518101516000848152600683526040908190208290558051828152339381019390935290925083917f941884a9a55191a7401466aaf8a0d2b7c8b082055a5a2b345b83c73940172ac4910160405180910390a250506001016109c3565b5050505050565b610a78610585565b8060026000828254610a8a9190612389565b90915550610a9790508181565b50565b6001546000036105ce57604051630f68fe6360e21b815260040160405180910390fd5b6040516343f6e4ab60e01b815260040160405180910390fd5b6000610ae06115f2565b3415610aff576040516322d8ddab60e01b815260040160405180910390fd5b6000806000610b21604051806040016040528060008152602001606081525090565b60035460ff1615610b735786806020019051810190610b409190612432565b91965093509050610b518587611641565b610b6e5760405163075fd2b160e01b815260040160405180910390fd5b610bde565b86806020019051810190610b879190612432565b6001600160a01b03831615159650909450909250905083610ba85785610baa565b815b9450838015610bc05750610bbe8587611641565b155b15610bde5760405163075fd2b160e01b815260040160405180910390fd5b600354610100900460ff168015610c0157506020810151511580610c0157508051155b15610c1f5760405163c19e07c560e01b815260040160405180910390fd5b6001600160a01b038316610c565760405163f4a513b960e01b81526001600160a01b03861660048201526024015b60405180910390fd5b6001600160a01b03808616600090815260086020908152604090912080549286166101000274ffffffffffffffffffffffffffffffffffffffff0019909316929092178255825160018301908155908301518391906002840190610cba9082612515565b505060035460ff169050610cce5784610cd1565b60015b815460ff19169015151781556001600160a01b0386166000908152600760205260408120549003610dad576004546001600160a01b038716600090815260076020526040902055610d278660015b60ff16611739565b600088600454604051602001610d3e9291906125d4565b6040516020818303038152906040529050866001600160a01b03167fa197306e3dd5494a61a695381aa809a53b8e377a685e84e404a85d5a8da6cc62828a604051610d8a9291906125f6565b60405180910390a260048054906000610da2836122c2565b919050555050610e4a565b6000610db88761176c565b905060ff811660021480610dcf575060ff81166005145b15610de457610ddf876001610d1f565b610dfb565b60021960ff821601610dfb57610dfb876004610d1f565b866001600160a01b03167fcec1da3f7f0b8a344dd1025d06e2ddd48b14880395997ad97cbdb439acc761d48a8a610e318b61176c565b604051610e4093929190612621565b60405180910390a2505b505050505092915050565b6001546040516329e40d4b60e01b81526000916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916329e40d4b91610eb99186906004019182526001600160a01b0316602082015260400190565b602060405180830381865afa158015610ed6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060f9190612656565b6001546040516329e40d4b60e01b815260048101919091526001600160a01b0382811660248301527f000000000000000000000000000000000000000000000000000000000000000016906329e40d4b90604401602060405180830381865afa158015610f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8f9190612656565b610a975760405163075fd2b160e01b815260040160405180910390fd5b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03841601610fe457506001600160a01b0381163161060f565b610fee83836117ad565b905061060f565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03841601611024576105eb82826117e2565b6105eb8383836117fe565b611037611b06565b6001600160a01b038083166000908152600860209081526040918290208251606081018452815460ff81161515825261010090049094168483015282518084018452600182018054825260028301805493958701949293919284019161109c90612495565b80601f01602080910402602001604051908101604052809291908181526020018280546110c890612495565b80156111155780601f106110ea57610100808354040283529160200191611115565b820191906000526020600020905b8154815290600101906020018083116110f857829003601f168201915b5050509190925250505090525092915050565b806001600160401b0316826001600160401b0316111561098e57604051637fcce2a960e01b815260040160405180910390fd5b606061060c83836040518060600160405280602781526020016128c66027913961184d565b6040805180820190915260008082526020820152610abd565b60035460009042620100009091046001600160401b0316118015906111d05750600354600160501b90046001600160401b03164211155b156111db5750600190565b50600090565b60006111ec8261176c565b60ff16600681111561060f5761060f6120f2565b611209826118c5565b80516003805460208085015161ffff1990921693151561ff001916939093176101009115159190910217905560408051635ab1bd5360e01b815290517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031692635ab1bd5392600480820193918290030181865afa158015611296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ba9190612671565b6005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055604081015160038054606084015171ffffffffffffffffffffffffffffffff000019909116620100006001600160401b038086169190910267ffffffffffffffff60501b191691909117600160501b918316919091021790915560016004556113509190611128565b60408082015160608084015183516001600160401b0393841681529216602083015233928201929092527f70d34c8836b996cffd8970ba5edf940d83ca7c8f30f738ea4fd8566a37d93359910160405180910390a15050565b806113b381610efa565b60003490506000848060200190518101906113ce9190612699565b805190915060008190036113f557604051637fcce2a960e01b815260040160405180910390fd5b60005b818110156115c457600083828151811061141457611414612249565b6020026020010151905060008160200151905060006114328261102f565b9050600081602001519050600087868151811061145157611451612249565b6020026020010151600001519050600088878151811061147357611473612249565b602002602001015160400151905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316826001600160a01b0316036114bb576114b8818b612768565b99505b60208401516001600160a01b03166114f15760405163f4a513b960e01b81526001600160a01b0386166004820152602401610c4d565b60026114fc8661176c565b60ff161461151d5760405163392c16fb60e21b815260040160405180910390fd5b6115538260405180606001604052808f6001600160a01b03168152602001866001600160a01b0316815260200184815250611914565b50846001600160a01b03167f463ffc2cf8b1596445c417388ed30e53eb67cf6668cb2be7f0addf8a78c8441b82848f6040516115ab939291909283526001600160a01b03918216602084015216604082015260600190565b60405180910390a28660010196505050505050506113f8565b5082156115ea576115ea73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8685610ff5565b505050505050565b60035442620100009091046001600160401b031611806116235750600354600160501b90046001600160401b031642115b156105ce57604051635b04f6ad60e11b815260040160405180910390fd5b60055460405163dd93da4360e01b81526001600160a01b038481166004830152600092839291169063dd93da4390602401600060405180830381865afa15801561168f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116b7919081019061277b565b6005548151604051635e8a791560e01b815260048101919091526001600160a01b038681166024830152929350911690635e8a791590604401602060405180830381865afa15801561170d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117319190612656565b949350505050565b600080600061174785611993565b60009283526006602052604090922095811b600f90911b199091161790935550505050565b6001600160a01b038116600090815260076020526040812054810361179357506000919050565b60008061179f84611993565b600f911c1695945050505050565b6000816014526f70a0823100000000000000000000000060005260208060246010865afa601f3d111660205102905092915050565b60008060008084865af161098e5763b12d13eb6000526004601cfd5b81601452806034526fa9059cbb00000000000000000000000060005260206000604460106000875af13d156001600051141716611843576390b8ec186000526004601cfd5b6000603452505050565b6060600080856001600160a01b03168560405161186a9190612841565b600060405180830381855af49150503d80600081146118a5576040519150601f19603f3d011682016040523d82523d6000602084013e6118aa565b606091505b50915091506118bb86838387611a06565b9695505050505050565b6118cd610585565b600154156118ee5760405163439a74c960e01b815260040160405180910390fd5b8060000361190f57604051637fcce2a960e01b815260040160405180910390fd5b600155565b604081015160009073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038516016119755780341015611962576040516374c5672b60e01b815260040160405180910390fd5b6119708360200151826117e2565b611989565b611989848460000151856020015184611a7f565b5060019392505050565b6001600160a01b0381166000908152600760205260408120548190819081906119be90600190612768565b905060006119cd604083612873565b905060006119dc604084612887565b6119e790600461289b565b6000838152600660205260409020549298909750919550909350505050565b60608315611a75578251600003611a6e576001600160a01b0385163b611a6e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c4d565b5081611731565b6117318383611adc565b60405181606052826040528360601b602c526f23b872dd000000000000000000000000600c52602060006064601c6000895af13d156001600051141716611ace57637939f4246000526004601cfd5b600060605260405250505050565b815115611aec5781518083602001fd5b8060405162461bcd60e51b8152600401610c4d91906128b2565b604051806060016040528060001515815260200160006001600160a01b03168152602001611b47604051806040016040528060008152602001606081525090565b905290565b6001600160a01b0381168114610a9757600080fd5b600060208284031215611b7357600080fd5b8135611b7e81611b4c565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715611bbd57611bbd611b85565b60405290565b604051606081016001600160401b0381118282101715611bbd57611bbd611b85565b60405160c081016001600160401b0381118282101715611bbd57611bbd611b85565b604051601f8201601f191681016001600160401b0381118282101715611c2f57611c2f611b85565b604052919050565b60006001600160401b03821115611c5057611c50611b85565b5060051b60200190565b600082601f830112611c6b57600080fd5b81356020611c80611c7b83611c37565b611c07565b82815260059290921b84018101918181019086841115611c9f57600080fd5b8286015b84811015611cc3578035611cb681611b4c565b8352918301918301611ca3565b509695505050505050565b60006001600160401b03821115611ce757611ce7611b85565b50601f01601f191660200190565b600082601f830112611d0657600080fd5b8135611d14611c7b82611cce565b818152846020838601011115611d2957600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215611d5b57600080fd5b83356001600160401b0380821115611d7257600080fd5b611d7e87838801611c5a565b94506020860135915080821115611d9457600080fd5b50611da186828701611cf5565b9250506040840135611db281611b4c565b809150509250925092565b60008060408385031215611dd057600080fd5b82356001600160401b03811115611de657600080fd5b611df285828601611cf5565b9250506020830135611e0381611b4c565b809150509250929050565b60005b83811015611e29578181015183820152602001611e11565b50506000910152565b60008151808452611e4a816020860160208601611e0e565b601f01601f19169290920160200192915050565b602081528151151560208201526001600160a01b036020830151166040820152600060408301516060808401528051608084015260208101519050604060a084015261173160c0840182611e32565b6001600160401b0381168114610a9757600080fd5b60008060408385031215611ed557600080fd5b8235611ee081611ead565b91506020830135611e0381611ead565b60008060208385031215611f0357600080fd5b82356001600160401b0380821115611f1a57600080fd5b818501915085601f830112611f2e57600080fd5b813581811115611f3d57600080fd5b8660208260051b8501011115611f5257600080fd5b60209290920196919550909350505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015611fb957603f19888603018452611fa7858351611e32565b94509285019290850190600101611f8b565b5092979650505050505050565b60008060408385031215611fd957600080fd5b82356001600160401b0380821115611ff057600080fd5b611ffc86838701611c5a565b935060209150818501358181111561201357600080fd5b8501601f8101871361202457600080fd5b8035612032611c7b82611c37565b81815260059190911b8201840190848101908983111561205157600080fd5b8584015b838110156120895780358681111561206d5760008081fd5b61207b8c8983890101611cf5565b845250918601918601612055565b508096505050505050509250929050565b602080825282518282018190526000919060409081850190868401855b828110156120e557815180516001600160a01b031685528601518685015292840192908501906001016120b7565b5091979650505050505050565b634e487b7160e01b600052602160045260246000fd5b602081016007831061212a57634e487b7160e01b600052602160045260246000fd5b91905290565b6000806040838503121561214357600080fd5b8235915060208301356001600160401b0381111561216057600080fd5b61216c85828601611cf5565b9150509250929050565b600080604080848603121561218a57600080fd5b83356001600160401b038111156121a057600080fd5b8401601f810186136121b157600080fd5b803560206121c1611c7b83611c37565b82815260069290921b830181019181810190898411156121e057600080fd5b938201935b838510156122205785858b0312156121fd5760008081fd5b612205611b9b565b853581528386013584820152825293850193908201906121e5565b9997909101359750505050505050565b60006020828403121561224257600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261227657600080fd5b8301803591506001600160401b0382111561229057600080fd5b6020019150368190038213156122a557600080fd5b9250929050565b634e487b7160e01b600052601160045260246000fd5b6000600182016122d4576122d46122ac565b5060010190565b805180151581146122eb57600080fd5b919050565b60006080828403121561230257600080fd5b604051608081018181106001600160401b038211171561232457612324611b85565b604052612330836122db565b815261233e602084016122db565b6020820152604083015161235181611ead565b6040820152606083015161236481611ead565b60608201529392505050565b8281526040602082015260006117316040830184611e32565b8082018082111561060f5761060f6122ac565b600082601f8301126123ad57600080fd5b81516123bb611c7b82611cce565b8181528460208386010111156123d057600080fd5b611731826020830160208701611e0e565b6000604082840312156123f357600080fd5b6123fb611b9b565b90508151815260208201516001600160401b0381111561241a57600080fd5b6124268482850161239c565b60208301525092915050565b60008060006060848603121561244757600080fd5b835161245281611b4c565b602085015190935061246381611b4c565b60408501519092506001600160401b0381111561247f57600080fd5b61248b868287016123e1565b9150509250925092565b600181811c908216806124a957607f821691505b6020821081036124c957634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156105eb57600081815260208120601f850160051c810160208610156124f65750805b601f850160051c820191505b818110156115ea57828155600101612502565b81516001600160401b0381111561252e5761252e611b85565b6125428161253c8454612495565b846124cf565b602080601f831160018114612577576000841561255f5750858301515b600019600386901b1c1916600185901b1785556115ea565b600085815260208120601f198616915b828110156125a657888601518255948401946001909101908401612587565b50858210156125c45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6040815260006125e76040830185611e32565b90508260208301529392505050565b6040815260006126096040830185611e32565b90506001600160a01b03831660208301529392505050565b6060815260006126346060830186611e32565b90506001600160a01b038416602083015260ff83166040830152949350505050565b60006020828403121561266857600080fd5b61060c826122db565b60006020828403121561268357600080fd5b8151611b7e81611b4c565b80516122eb81611b4c565b600060208083850312156126ac57600080fd5b82516001600160401b038111156126c257600080fd5b8301601f810185136126d357600080fd5b80516126e1611c7b82611c37565b8181526060918202830184019184820191908884111561270057600080fd5b938501935b8385101561275c5780858a03121561271d5760008081fd5b612725611bc3565b855161273081611b4c565b81528587015161273f81611b4c565b818801526040868101519082015283529384019391850191612705565b50979650505050505050565b8181038181111561060f5761060f6122ac565b60006020828403121561278d57600080fd5b81516001600160401b03808211156127a457600080fd5b9083019060c082860312156127b857600080fd5b6127c0611be5565b82518152602083015160208201526040830151828111156127e057600080fd5b6127ec8782860161239c565b60408301525060608301518281111561280457600080fd5b612810878286016123e1565b6060830152506128226080840161268e565b608082015261283360a0840161268e565b60a082015295945050505050565b60008251612853818460208701611e0e565b9190910192915050565b634e487b7160e01b600052601260045260246000fd5b6000826128825761288261285d565b500490565b6000826128965761289661285d565b500690565b808202811582820484141761060f5761060f6122ac565b60208152600061060c6020830184611e3256fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212206eece4c0fef0132b2728a7c3ff64467c881f80749d4c23f80868f1b32717dcab64736f6c634300081300330000000000000000000000001133ea7af70876e64665ecd07c0a0476d09465a10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001c4469726563744772616e74734c697465537472617465677976312e3000000000
Deployed Bytecode
0x6080604052600436106101a55760003560e01c80639af5c09d116100e1578063dff7d2c71161008a578063ef2920fc11610064578063ef2920fc14610505578063f31db3d114610518578063f5b0dfb714610538578063f6f258911461055857600080fd5b8063dff7d2c714610491578063eb11af93146104b8578063edd146cc146104e557600080fd5b8063b2b878d0116100bb578063b2b878d014610430578063cb0e85a61461045d578063df868ed31461047c57600080fd5b80639af5c09d1461039d578063a0cf0aea146103db578063ac9650d81461040357600080fd5b80634ab4ba421161014e5780635708973911610128578063570897391461032057806362812a391461033a57806375777aaa1461036757806395355b3b1461038757600080fd5b80634ab4ba42146102bb5780634d31d087146102d057806351cff8d91461030057600080fd5b80632bbe0cae1161017f5780632bbe0cae1461026057806338fff2d01461027357806342fda9c71461028857600080fd5b806301fc1c64146101b95780630a6f0ee9146101f957806315cc481e1461021957600080fd5b366101b4576101b2610585565b005b600080fd5b3480156101c557600080fd5b506101e66101d4366004611b61565b60076020526000908152604090205481565b6040519081526020015b60405180910390f35b34801561020557600080fd5b506101b2610214366004611d46565b6105d0565b34801561022557600080fd5b507f0000000000000000000000001133ea7af70876e64665ecd07c0a0476d09465a15b6040516001600160a01b0390911681526020016101f0565b61024861026e366004611dbd565b6105f0565b34801561027f57600080fd5b506001546101e6565b34801561029457600080fd5b507f103732a8e473467a510d4128ee11065262bdd978f0d9dad89ba68f2c56127e276101e6565b3480156102c757600080fd5b506002546101e6565b3480156102dc57600080fd5b506102f06102eb366004611b61565b610615565b60405190151581526020016101f0565b34801561030c57600080fd5b506101b261031b366004611b61565b610620565b34801561032c57600080fd5b506003546102f09060ff1681565b34801561034657600080fd5b5061035a610355366004611b61565b61064a565b6040516101f09190611e5e565b34801561037357600080fd5b506101b2610382366004611ec2565b61065b565b34801561039357600080fd5b506101e660045481565b3480156103a957600080fd5b506003546103c3906201000090046001600160401b031681565b6040516001600160401b0390911681526020016101f0565b3480156103e757600080fd5b5061024873eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561040f57600080fd5b5061042361041e366004611ef0565b61070d565b6040516101f09190611f64565b34801561043c57600080fd5b5061045061044b366004611fc6565b610801565b6040516101f0919061209a565b34801561046957600080fd5b506003546102f090610100900460ff1681565b34801561048857600080fd5b506102f06108ff565b34801561049d57600080fd5b506003546103c390600160501b90046001600160401b031681565b3480156104c457600080fd5b506104d86104d3366004611b61565b61090e565b6040516101f09190612108565b3480156104f157600080fd5b506101b2610500366004612130565b610919565b6101b2610513366004611dbd565b610974565b34801561052457600080fd5b506101b2610533366004612176565b610992565b34801561054457600080fd5b506101b2610553366004612230565b610a70565b34801561056457600080fd5b506101e6610573366004612230565b60066020526000908152604090205481565b336001600160a01b037f0000000000000000000000001133ea7af70876e64665ecd07c0a0476d09465a116146105ce5760405163075fd2b160e01b815260040160405180910390fd5b565b6105d8610585565b6105e0610a9a565b6105eb838383610abd565b505050565b60006105fa610585565b610602610a9a565b61060c8383610ad6565b90505b92915050565b600061060f82610e55565b3361062a81610efa565b60006106368330610fac565b905080610644843383610ff5565b50505050565b610652611b06565b61060f8261102f565b3361066581610efa565b61066f8383611128565b6003805471ffffffffffffffffffffffffffffffff00001916620100006001600160401b03868116820267ffffffffffffffff60501b191692909217600160501b8684168102919091179384905560408051928504841683529304909116602082015233918101919091527f70d34c8836b996cffd8970ba5edf940d83ca7c8f30f738ea4fd8566a37d93359906060015b60405180910390a1505050565b6060816001600160401b0381111561072757610727611b85565b60405190808252806020026020018201604052801561075a57816020015b60608152602001906001900390816107455790505b50905060005b828110156107fa576107ca3085858481811061077e5761077e612249565b9050602002810190610790919061225f565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061115b92505050565b8282815181106107dc576107dc612249565b602002602001018190525080806107f2906122c2565b915050610760565b5092915050565b8151815160609190811461082857604051633da4c02b60e11b815260040160405180910390fd5b6000816001600160401b0381111561084257610842611b85565b60405190808252806020026020018201604052801561088757816020015b60408051808201909152600080825260208201528152602001906001900390816108605790505b50905060005b828110156108f6576108d18682815181106108aa576108aa612249565b60200260200101518683815181106108c4576108c4612249565b6020026020010151611180565b8282815181106108e3576108e3612249565b602090810291909101015260010161088d565b50949350505050565b6000610909611199565b905090565b600061060f826111e1565b610921610585565b60008180602001905181019061093791906122f0565b90506109438382611200565b7f91efa3d50feccde0d0d202f8ae5c41ca0b2be614cebcb2bd2f4b019396e6568a8383604051610700929190612370565b61097c610585565b610984610a9a565b61098e82826113a9565b5050565b3361099c81610efa565b60045482146109be57604051637fcce2a960e01b815260040160405180910390fd5b825160005b81811015610a695760008582815181106109df576109df612249565b60200260200101516000015190506000868381518110610a0157610a01612249565b6020908102919091018101518101516000848152600683526040908190208290558051828152339381019390935290925083917f941884a9a55191a7401466aaf8a0d2b7c8b082055a5a2b345b83c73940172ac4910160405180910390a250506001016109c3565b5050505050565b610a78610585565b8060026000828254610a8a9190612389565b90915550610a9790508181565b50565b6001546000036105ce57604051630f68fe6360e21b815260040160405180910390fd5b6040516343f6e4ab60e01b815260040160405180910390fd5b6000610ae06115f2565b3415610aff576040516322d8ddab60e01b815260040160405180910390fd5b6000806000610b21604051806040016040528060008152602001606081525090565b60035460ff1615610b735786806020019051810190610b409190612432565b91965093509050610b518587611641565b610b6e5760405163075fd2b160e01b815260040160405180910390fd5b610bde565b86806020019051810190610b879190612432565b6001600160a01b03831615159650909450909250905083610ba85785610baa565b815b9450838015610bc05750610bbe8587611641565b155b15610bde5760405163075fd2b160e01b815260040160405180910390fd5b600354610100900460ff168015610c0157506020810151511580610c0157508051155b15610c1f5760405163c19e07c560e01b815260040160405180910390fd5b6001600160a01b038316610c565760405163f4a513b960e01b81526001600160a01b03861660048201526024015b60405180910390fd5b6001600160a01b03808616600090815260086020908152604090912080549286166101000274ffffffffffffffffffffffffffffffffffffffff0019909316929092178255825160018301908155908301518391906002840190610cba9082612515565b505060035460ff169050610cce5784610cd1565b60015b815460ff19169015151781556001600160a01b0386166000908152600760205260408120549003610dad576004546001600160a01b038716600090815260076020526040902055610d278660015b60ff16611739565b600088600454604051602001610d3e9291906125d4565b6040516020818303038152906040529050866001600160a01b03167fa197306e3dd5494a61a695381aa809a53b8e377a685e84e404a85d5a8da6cc62828a604051610d8a9291906125f6565b60405180910390a260048054906000610da2836122c2565b919050555050610e4a565b6000610db88761176c565b905060ff811660021480610dcf575060ff81166005145b15610de457610ddf876001610d1f565b610dfb565b60021960ff821601610dfb57610dfb876004610d1f565b866001600160a01b03167fcec1da3f7f0b8a344dd1025d06e2ddd48b14880395997ad97cbdb439acc761d48a8a610e318b61176c565b604051610e4093929190612621565b60405180910390a2505b505050505092915050565b6001546040516329e40d4b60e01b81526000916001600160a01b037f0000000000000000000000001133ea7af70876e64665ecd07c0a0476d09465a116916329e40d4b91610eb99186906004019182526001600160a01b0316602082015260400190565b602060405180830381865afa158015610ed6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060f9190612656565b6001546040516329e40d4b60e01b815260048101919091526001600160a01b0382811660248301527f0000000000000000000000001133ea7af70876e64665ecd07c0a0476d09465a116906329e40d4b90604401602060405180830381865afa158015610f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f8f9190612656565b610a975760405163075fd2b160e01b815260040160405180910390fd5b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03841601610fe457506001600160a01b0381163161060f565b610fee83836117ad565b905061060f565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03841601611024576105eb82826117e2565b6105eb8383836117fe565b611037611b06565b6001600160a01b038083166000908152600860209081526040918290208251606081018452815460ff81161515825261010090049094168483015282518084018452600182018054825260028301805493958701949293919284019161109c90612495565b80601f01602080910402602001604051908101604052809291908181526020018280546110c890612495565b80156111155780601f106110ea57610100808354040283529160200191611115565b820191906000526020600020905b8154815290600101906020018083116110f857829003601f168201915b5050509190925250505090525092915050565b806001600160401b0316826001600160401b0316111561098e57604051637fcce2a960e01b815260040160405180910390fd5b606061060c83836040518060600160405280602781526020016128c66027913961184d565b6040805180820190915260008082526020820152610abd565b60035460009042620100009091046001600160401b0316118015906111d05750600354600160501b90046001600160401b03164211155b156111db5750600190565b50600090565b60006111ec8261176c565b60ff16600681111561060f5761060f6120f2565b611209826118c5565b80516003805460208085015161ffff1990921693151561ff001916939093176101009115159190910217905560408051635ab1bd5360e01b815290517f0000000000000000000000001133ea7af70876e64665ecd07c0a0476d09465a16001600160a01b031692635ab1bd5392600480820193918290030181865afa158015611296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ba9190612671565b6005805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055604081015160038054606084015171ffffffffffffffffffffffffffffffff000019909116620100006001600160401b038086169190910267ffffffffffffffff60501b191691909117600160501b918316919091021790915560016004556113509190611128565b60408082015160608084015183516001600160401b0393841681529216602083015233928201929092527f70d34c8836b996cffd8970ba5edf940d83ca7c8f30f738ea4fd8566a37d93359910160405180910390a15050565b806113b381610efa565b60003490506000848060200190518101906113ce9190612699565b805190915060008190036113f557604051637fcce2a960e01b815260040160405180910390fd5b60005b818110156115c457600083828151811061141457611414612249565b6020026020010151905060008160200151905060006114328261102f565b9050600081602001519050600087868151811061145157611451612249565b6020026020010151600001519050600088878151811061147357611473612249565b602002602001015160400151905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316826001600160a01b0316036114bb576114b8818b612768565b99505b60208401516001600160a01b03166114f15760405163f4a513b960e01b81526001600160a01b0386166004820152602401610c4d565b60026114fc8661176c565b60ff161461151d5760405163392c16fb60e21b815260040160405180910390fd5b6115538260405180606001604052808f6001600160a01b03168152602001866001600160a01b0316815260200184815250611914565b50846001600160a01b03167f463ffc2cf8b1596445c417388ed30e53eb67cf6668cb2be7f0addf8a78c8441b82848f6040516115ab939291909283526001600160a01b03918216602084015216604082015260600190565b60405180910390a28660010196505050505050506113f8565b5082156115ea576115ea73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8685610ff5565b505050505050565b60035442620100009091046001600160401b031611806116235750600354600160501b90046001600160401b031642115b156105ce57604051635b04f6ad60e11b815260040160405180910390fd5b60055460405163dd93da4360e01b81526001600160a01b038481166004830152600092839291169063dd93da4390602401600060405180830381865afa15801561168f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526116b7919081019061277b565b6005548151604051635e8a791560e01b815260048101919091526001600160a01b038681166024830152929350911690635e8a791590604401602060405180830381865afa15801561170d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117319190612656565b949350505050565b600080600061174785611993565b60009283526006602052604090922095811b600f90911b199091161790935550505050565b6001600160a01b038116600090815260076020526040812054810361179357506000919050565b60008061179f84611993565b600f911c1695945050505050565b6000816014526f70a0823100000000000000000000000060005260208060246010865afa601f3d111660205102905092915050565b60008060008084865af161098e5763b12d13eb6000526004601cfd5b81601452806034526fa9059cbb00000000000000000000000060005260206000604460106000875af13d156001600051141716611843576390b8ec186000526004601cfd5b6000603452505050565b6060600080856001600160a01b03168560405161186a9190612841565b600060405180830381855af49150503d80600081146118a5576040519150601f19603f3d011682016040523d82523d6000602084013e6118aa565b606091505b50915091506118bb86838387611a06565b9695505050505050565b6118cd610585565b600154156118ee5760405163439a74c960e01b815260040160405180910390fd5b8060000361190f57604051637fcce2a960e01b815260040160405180910390fd5b600155565b604081015160009073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038516016119755780341015611962576040516374c5672b60e01b815260040160405180910390fd5b6119708360200151826117e2565b611989565b611989848460000151856020015184611a7f565b5060019392505050565b6001600160a01b0381166000908152600760205260408120548190819081906119be90600190612768565b905060006119cd604083612873565b905060006119dc604084612887565b6119e790600461289b565b6000838152600660205260409020549298909750919550909350505050565b60608315611a75578251600003611a6e576001600160a01b0385163b611a6e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c4d565b5081611731565b6117318383611adc565b60405181606052826040528360601b602c526f23b872dd000000000000000000000000600c52602060006064601c6000895af13d156001600051141716611ace57637939f4246000526004601cfd5b600060605260405250505050565b815115611aec5781518083602001fd5b8060405162461bcd60e51b8152600401610c4d91906128b2565b604051806060016040528060001515815260200160006001600160a01b03168152602001611b47604051806040016040528060008152602001606081525090565b905290565b6001600160a01b0381168114610a9757600080fd5b600060208284031215611b7357600080fd5b8135611b7e81611b4c565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715611bbd57611bbd611b85565b60405290565b604051606081016001600160401b0381118282101715611bbd57611bbd611b85565b60405160c081016001600160401b0381118282101715611bbd57611bbd611b85565b604051601f8201601f191681016001600160401b0381118282101715611c2f57611c2f611b85565b604052919050565b60006001600160401b03821115611c5057611c50611b85565b5060051b60200190565b600082601f830112611c6b57600080fd5b81356020611c80611c7b83611c37565b611c07565b82815260059290921b84018101918181019086841115611c9f57600080fd5b8286015b84811015611cc3578035611cb681611b4c565b8352918301918301611ca3565b509695505050505050565b60006001600160401b03821115611ce757611ce7611b85565b50601f01601f191660200190565b600082601f830112611d0657600080fd5b8135611d14611c7b82611cce565b818152846020838601011115611d2957600080fd5b816020850160208301376000918101602001919091529392505050565b600080600060608486031215611d5b57600080fd5b83356001600160401b0380821115611d7257600080fd5b611d7e87838801611c5a565b94506020860135915080821115611d9457600080fd5b50611da186828701611cf5565b9250506040840135611db281611b4c565b809150509250925092565b60008060408385031215611dd057600080fd5b82356001600160401b03811115611de657600080fd5b611df285828601611cf5565b9250506020830135611e0381611b4c565b809150509250929050565b60005b83811015611e29578181015183820152602001611e11565b50506000910152565b60008151808452611e4a816020860160208601611e0e565b601f01601f19169290920160200192915050565b602081528151151560208201526001600160a01b036020830151166040820152600060408301516060808401528051608084015260208101519050604060a084015261173160c0840182611e32565b6001600160401b0381168114610a9757600080fd5b60008060408385031215611ed557600080fd5b8235611ee081611ead565b91506020830135611e0381611ead565b60008060208385031215611f0357600080fd5b82356001600160401b0380821115611f1a57600080fd5b818501915085601f830112611f2e57600080fd5b813581811115611f3d57600080fd5b8660208260051b8501011115611f5257600080fd5b60209290920196919550909350505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015611fb957603f19888603018452611fa7858351611e32565b94509285019290850190600101611f8b565b5092979650505050505050565b60008060408385031215611fd957600080fd5b82356001600160401b0380821115611ff057600080fd5b611ffc86838701611c5a565b935060209150818501358181111561201357600080fd5b8501601f8101871361202457600080fd5b8035612032611c7b82611c37565b81815260059190911b8201840190848101908983111561205157600080fd5b8584015b838110156120895780358681111561206d5760008081fd5b61207b8c8983890101611cf5565b845250918601918601612055565b508096505050505050509250929050565b602080825282518282018190526000919060409081850190868401855b828110156120e557815180516001600160a01b031685528601518685015292840192908501906001016120b7565b5091979650505050505050565b634e487b7160e01b600052602160045260246000fd5b602081016007831061212a57634e487b7160e01b600052602160045260246000fd5b91905290565b6000806040838503121561214357600080fd5b8235915060208301356001600160401b0381111561216057600080fd5b61216c85828601611cf5565b9150509250929050565b600080604080848603121561218a57600080fd5b83356001600160401b038111156121a057600080fd5b8401601f810186136121b157600080fd5b803560206121c1611c7b83611c37565b82815260069290921b830181019181810190898411156121e057600080fd5b938201935b838510156122205785858b0312156121fd5760008081fd5b612205611b9b565b853581528386013584820152825293850193908201906121e5565b9997909101359750505050505050565b60006020828403121561224257600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b6000808335601e1984360301811261227657600080fd5b8301803591506001600160401b0382111561229057600080fd5b6020019150368190038213156122a557600080fd5b9250929050565b634e487b7160e01b600052601160045260246000fd5b6000600182016122d4576122d46122ac565b5060010190565b805180151581146122eb57600080fd5b919050565b60006080828403121561230257600080fd5b604051608081018181106001600160401b038211171561232457612324611b85565b604052612330836122db565b815261233e602084016122db565b6020820152604083015161235181611ead565b6040820152606083015161236481611ead565b60608201529392505050565b8281526040602082015260006117316040830184611e32565b8082018082111561060f5761060f6122ac565b600082601f8301126123ad57600080fd5b81516123bb611c7b82611cce565b8181528460208386010111156123d057600080fd5b611731826020830160208701611e0e565b6000604082840312156123f357600080fd5b6123fb611b9b565b90508151815260208201516001600160401b0381111561241a57600080fd5b6124268482850161239c565b60208301525092915050565b60008060006060848603121561244757600080fd5b835161245281611b4c565b602085015190935061246381611b4c565b60408501519092506001600160401b0381111561247f57600080fd5b61248b868287016123e1565b9150509250925092565b600181811c908216806124a957607f821691505b6020821081036124c957634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156105eb57600081815260208120601f850160051c810160208610156124f65750805b601f850160051c820191505b818110156115ea57828155600101612502565b81516001600160401b0381111561252e5761252e611b85565b6125428161253c8454612495565b846124cf565b602080601f831160018114612577576000841561255f5750858301515b600019600386901b1c1916600185901b1785556115ea565b600085815260208120601f198616915b828110156125a657888601518255948401946001909101908401612587565b50858210156125c45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6040815260006125e76040830185611e32565b90508260208301529392505050565b6040815260006126096040830185611e32565b90506001600160a01b03831660208301529392505050565b6060815260006126346060830186611e32565b90506001600160a01b038416602083015260ff83166040830152949350505050565b60006020828403121561266857600080fd5b61060c826122db565b60006020828403121561268357600080fd5b8151611b7e81611b4c565b80516122eb81611b4c565b600060208083850312156126ac57600080fd5b82516001600160401b038111156126c257600080fd5b8301601f810185136126d357600080fd5b80516126e1611c7b82611c37565b8181526060918202830184019184820191908884111561270057600080fd5b938501935b8385101561275c5780858a03121561271d5760008081fd5b612725611bc3565b855161273081611b4c565b81528587015161273f81611b4c565b818801526040868101519082015283529384019391850191612705565b50979650505050505050565b8181038181111561060f5761060f6122ac565b60006020828403121561278d57600080fd5b81516001600160401b03808211156127a457600080fd5b9083019060c082860312156127b857600080fd5b6127c0611be5565b82518152602083015160208201526040830151828111156127e057600080fd5b6127ec8782860161239c565b60408301525060608301518281111561280457600080fd5b612810878286016123e1565b6060830152506128226080840161268e565b608082015261283360a0840161268e565b60a082015295945050505050565b60008251612853818460208701611e0e565b9190910192915050565b634e487b7160e01b600052601260045260246000fd5b6000826128825761288261285d565b500490565b6000826128965761289661285d565b500690565b808202811582820484141761060f5761060f6122ac565b60208152600061060c6020830184611e3256fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212206eece4c0fef0132b2728a7c3ff64467c881f80749d4c23f80868f1b32717dcab64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001133ea7af70876e64665ecd07c0a0476d09465a10000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001c4469726563744772616e74734c697465537472617465677976312e3000000000
-----Decoded View---------------
Arg [0] : _allo (address): 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
Arg [1] : _name (string): DirectGrantsLiteStrategyv1.0
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000001133ea7af70876e64665ecd07c0a0476d09465a1
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [2] : 000000000000000000000000000000000000000000000000000000000000001c
Arg [3] : 4469726563744772616e74734c697465537472617465677976312e3000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.