Skip to content

Commit

Permalink
Merge pull request #1 from agentcoinorg/nerfzael/migration
Browse files Browse the repository at this point in the history
Migration implementation and deployment improvements
  • Loading branch information
dOrgJelli authored Nov 4, 2024
2 parents 28ab0d9 + d06a232 commit bd4338f
Show file tree
Hide file tree
Showing 12 changed files with 367 additions and 298 deletions.
18 changes: 18 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FORGE_ACCOUNT=<NAME-OF-FORGE-ACCOUNT-IF-NOT-USING-PK> # Only needed if you want to deploy with a forge account instead of a private key
BASESCAN_API_KEY=<BASESCAN-API-KEY> # Only needed if you want to verify the contract on Basescan

BASE_TOKEN_NAME=<TOKEN-NAME>
BASE_TOKEN_SYMBOL=<TOKEN-SYMBOL>
BASE_BENEFICIARY=<BENEFICIARY>
BASE_RPC_URL=<RPC-URL-OF-BASE-NETWORK>
BASE_CONTROL=<CONTROL>
BASE_FEE_COLLECTOR=<FEE-COLLECTOR>
BASE_PRICE_INCREASE=<PRICE-INCREASE> # Price increase in ether (wei), e.g. 200000000000000 for 0.0002 ETH

BASE_SEPOLIA_TOKEN_NAME=<TOKEN-NAME>
BASE_SEPOLIA_TOKEN_SYMBOL=<TOKEN-SYMBOL>
BASE_SEPOLIA_BENEFICIARY=<BENEFICIARY>
BASE_SEPOLIA_RPC_URL=<RPC-URL-OF-BASE-SEPOLIA-NETWORK>
BASE_SEPOLIA_CONTROL=<CONTROL>
BASE_SEPOLIA_FEE_COLLECTOR=<FEE-COLLECTOR>
BASE_SEPOLIA_PRICE_INCREASE=<PRICE-INCREASE> # Price increase in ether (wei), e.g. 200000000000000 for 0.0002 ETH
26 changes: 25 additions & 1 deletion deploy/base-sepolia.sh
Original file line number Diff line number Diff line change
@@ -1 +1,25 @@
forge script ./script/DeployAgentKey.s.sol --rpc-url https://sepolia.base.org/ --broadcast --interactives 1 -g 200 --force --verify --verifier-url https://api-sepolia.basescan.org/api --etherscan-api-key $1
if [[ $1 = "pk" ]]; then
export $(cat .env | xargs) && \
forge script ./script/DeployAgentKey.s.sol \
--rpc-url $BASE_SEPOLIA_RPC_URL \
--broadcast \
-g 200 \
--force \
--verify \
--verifier-url https://api-sepolia.basescan.org/api \
--etherscan-api-key $BASESCAN_API_KEY \
--interactives 1 \
--slow
else
export $(cat .env | xargs) && \
forge script ./script/DeployAgentKey.s.sol \
--rpc-url $BASE_SEPOLIA_RPC_URL \
--broadcast \
-g 200 \
--force \
--verify \
--verifier-url https://api-sepolia.basescan.org/api \
--etherscan-api-key $BASESCAN_API_KEY \
--account $FORGE_ACCOUNT \
--slow
fi
25 changes: 25 additions & 0 deletions deploy/base.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
if [[ $1 = "pk" ]]; then
export $(cat .env | xargs) && \
forge script ./script/DeployAgentKey.s.sol \
--rpc-url $BASE_RPC_URL \
--broadcast \
-g 200 \
--force \
--verify \
--verifier-url https://api.basescan.org/api \
--etherscan-api-key $BASESCAN_API_KEY \
--interactives 1 \
--slow
else
export $(cat .env | xargs) && \
forge script ./script/DeployAgentKey.s.sol \
--rpc-url $BASE_RPC_URL \
--broadcast \
-g 200 \
--force \
--verify \
--verifier-url https://api.basescan.org/api \
--etherscan-api-key $BASESCAN_API_KEY \
--account $FORGE_ACCOUNT \
--slow
fi
1 change: 0 additions & 1 deletion deploy/local.sh

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
"scripts": {},
"dependencies": {},
"devDependencies": {
"@fairmint/c-org-contracts": "^2.4.24"
"@fairmint/c-org-contracts": "git+https://github.com/Fairmint/c-org#1770aa5d527175a676269ad80f458c46b30456ac"
}
}
45 changes: 18 additions & 27 deletions script/DeployAgentKey.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,47 +16,38 @@ contract DeployAgentKey is Script {
deploy(helper.getConfig());
}

function deploy(
HelperConfig.AgentKeyConfig memory config
) public returns (IAgentKey key, address whitelist) {
function deploy(HelperConfig.AgentKeyConfig memory config) public returns (IAgentKey key, address whitelist) {
{
uint256 initReserve = 0 ether;
address currencyAddress = address(0);
uint256 initGoal = 0;
uint256 setupFee = 0;
address payable setupFeeRecipient = payable(address(0));
string memory name = "Agent Keys";
string memory symbol = "KEYS";

// buySlopeNum and buySlopeDen are used for the formula in: https://github.com/Fairmint/c-org/blob/781d1ed8d70d733eed57c5e7fff8931b096de0e9/contracts/ContinuousOffering.sol#L495
bytes memory ctorArgs = abi.encode(
initReserve,
currencyAddress,
initGoal,
config.buySlopeNum,
config.buySlopeDen,
0 ether, // initReserve
address(0), // currencyAddress
0, // initGoal
2, // buySlopeNum
50000000 * config.priceIncrease, // buySlopeDen
config.investmentReserveBasisPoints,
setupFee,
setupFeeRecipient,
name,
symbol
);
0, // setupFee
payable(address(0)), // setupFeeRecipient
config.name,
config.symbol
);

vm.startBroadcast();

key = IAgentKey(deployCode("AgentKey.sol:AgentKey", ctorArgs));
}

whitelist = address(new AgentKeyWhitelist());

key.updateConfig(
whitelist,
whitelist,
config.beneficiary,
config.control,
config.feeCollector,
config.feeBasisPoints,
config.revenueCommitmentBasisPoints,
1,
0
1, // minInvestment
0 // minDuration
);

vm.stopBroadcast();
Expand Down
66 changes: 32 additions & 34 deletions script/HelperConfig.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,64 +4,62 @@ pragma solidity ^0.8.13;
import {Script, console} from "forge-std/Script.sol";

abstract contract Constants {
uint256 public constant CHAIN_ID_LOCAL = 31337;
uint256 public constant CHAIN_ID_BASE = 8453;
uint256 public constant CHAIN_ID_BASE_SEPOLIA = 84532;
}

contract HelperConfig is Constants, Script {
struct AgentKeyConfig {
uint256 buySlopeNum;
uint256 buySlopeDen;
string name;
string symbol;
uint256 priceIncrease;
uint256 investmentReserveBasisPoints;
uint feeBasisPoints;
uint revenueCommitmentBasisPoints;
uint256 feeBasisPoints;
uint256 revenueCommitmentBasisPoints;
address payable beneficiary;
address control;
address payable feeCollector;
}

AgentKeyConfig public localAgentKeyConfig;
mapping (uint256 chainId => AgentKeyConfig) public agentKeyConfigs;

constructor() {
agentKeyConfigs[CHAIN_ID_LOCAL] = getLocalAnvilConfig();
agentKeyConfigs[CHAIN_ID_BASE_SEPOLIA] = getBaseSepoliaConfig();
}

function getConfig() public view returns (AgentKeyConfig memory) {
return getConfigByChainId(block.chainid);
}

function getConfigByChainId(uint256 chainId) private view returns (AgentKeyConfig memory) {
return agentKeyConfigs[chainId];
if (chainId == CHAIN_ID_BASE_SEPOLIA) {
return getBaseSepoliaConfig();
} else if (chainId == CHAIN_ID_BASE) {
return getBaseConfig();
} else {
revert("Unsupported chain id");
}
}

function getLocalAnvilConfig() private pure returns (AgentKeyConfig memory) {
function getBaseConfig() private view returns (AgentKeyConfig memory) {
return AgentKeyConfig({
buySlopeNum: 2,
buySlopeDen: 10000 * 1e18,
investmentReserveBasisPoints: 9500,
// First address derived from mnemonic: test test test test test test test test test test test junk
beneficiary: payable(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266),
// Second address
control: address(0x70997970C51812dc3A010C7d01b50e0d17dc79C8),
// Third address
feeCollector: payable(0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC),
feeBasisPoints: 1000,
name: vm.envString("BASE_TOKEN_NAME"),
symbol: vm.envString("BASE_TOKEN_SYMBOL"),
priceIncrease: vm.envUint("BASE_PRICE_INCREASE"),
investmentReserveBasisPoints: 9000,
beneficiary: payable(vm.envAddress("BASE_BENEFICIARY")),
control: vm.envAddress("BASE_CONTROL"),
feeCollector: payable(vm.envAddress("BASE_FEE_COLLECTOR")),
feeBasisPoints: 5000,
revenueCommitmentBasisPoints: 9500
});
}

function getBaseSepoliaConfig() private pure returns (AgentKeyConfig memory) {
function getBaseSepoliaConfig() private view returns (AgentKeyConfig memory) {
return AgentKeyConfig({
buySlopeNum: 2,
buySlopeDen: 10000 * 1e18,
investmentReserveBasisPoints: 9500,
beneficiary: payable(0x857766085629c1d68704989974A968cbdbf2fc3f),
control: 0x857766085629c1d68704989974A968cbdbf2fc3f,
feeCollector: payable(0x857766085629c1d68704989974A968cbdbf2fc3f),
feeBasisPoints: 1000,
name: vm.envString("BASE_SEPOLIA_TOKEN_NAME"),
symbol: vm.envString("BASE_SEPOLIA_TOKEN_SYMBOL"),
priceIncrease: vm.envUint("BASE_SEPOLIA_PRICE_INCREASE"),
investmentReserveBasisPoints: 9000,
beneficiary: payable(vm.envAddress("BASE_SEPOLIA_BENEFICIARY")),
control: vm.envAddress("BASE_SEPOLIA_CONTROL"),
feeCollector: payable(vm.envAddress("BASE_SEPOLIA_FEE_COLLECTOR")),
feeBasisPoints: 5000,
revenueCommitmentBasisPoints: 9500
});
}
}
}
41 changes: 34 additions & 7 deletions src/AgentKey.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@
pragma solidity 0.5.17;

import {DecentralizedAutonomousTrust} from "@fairmint/contracts/DecentralizedAutonomousTrust.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/utils/Address.sol";

contract AgentKey is DecentralizedAutonomousTrust {
bool public isStopped;

constructor(
uint _initReserve,
uint256 _initReserve,
address _currencyAddress,
uint _initGoal,
uint _buySlopeNum,
uint _buySlopeDen,
uint _investmentReserveBasisPoints,
uint _setupFee,
uint256 _initGoal,
uint256 _buySlopeNum,
uint256 _buySlopeDen,
uint256 _investmentReserveBasisPoints,
uint256 _setupFee,
address payable _setupFeeRecipient,
string memory _name,
string memory _symbol
Expand All @@ -26,7 +29,31 @@ contract AgentKey is DecentralizedAutonomousTrust {
_setupFee,
_setupFeeRecipient,
_name,
_symbol
_symbol
);
}

/// @notice Stops the contract and transfers the reserve to the recipient. To be used in case of a migration to a new contract.
function stopAndTransferReserve(address payable _recipient) external {
require(msg.sender == beneficiary, "BENEFICIARY_ONLY");
isStopped = true;
Address.sendValue(_recipient, address(this).balance);
}

/// @dev Overrides the modifier in ContinuousOffering
modifier authorizeTransfer(
address _from,
address _to,
uint256 _value,
bool _isSell
) {
if (isStopped) {
revert("Contract is stopped");
}
if (address(whitelist) != address(0)) {
// This is not set for the minting of initialReserve
whitelist.authorizeTransfer(_from, _to, _value, _isSell);
}
_;
}
}
14 changes: 3 additions & 11 deletions src/AgentKeyWhitelist.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,7 @@
pragma solidity ^0.8.13;

contract AgentKeyWhitelist {
function authorizeTransfer(
address _from,
address _to,
uint,
bool
) external pure {
require(
_from == address(0) || _to == address(0),
"TRANSFERS_DISABLED"
);
function authorizeTransfer(address _from, address _to, uint256, bool) external pure {
require(_from == address(0) || _to == address(0), "TRANSFERS_DISABLED");
}
}
}
34 changes: 12 additions & 22 deletions src/IAgentKey.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,28 @@ pragma solidity ^0.8.13;

interface IAgentKey {
function approve(address spender, uint256 amount) external returns (bool);
function buy(
address _to,
uint256 _currencyValue,
uint256 _minTokensBought
) external payable;
function sell(
address payable _to,
uint _quantityToSell,
uint _minCurrencyReturned
) external;
function estimateBuyValue(
uint256 _currencyValue
) external view returns (uint256);
function estimateSellValue(
uint _quantityToSell
) external view returns(uint256);
function buy(address _to, uint256 _currencyValue, uint256 _minTokensBought) external payable;
function sell(address payable _to, uint256 _quantityToSell, uint256 _minCurrencyReturned) external;
function estimateBuyValue(uint256 _currencyValue) external view returns (uint256);
function estimateSellValue(uint256 _quantityToSell) external view returns (uint256);
function balanceOf(address _owner) external view returns (uint256);
function state() external view returns (uint256);
function updateConfig(
address _whitelistAddress,
address payable _beneficiary,
address _control,
address payable _feeCollector,
uint _feeBasisPoints,
uint _revenueCommitmentBasisPoints,
uint _minInvestment,
uint _minDuration
uint256 _feeBasisPoints,
uint256 _revenueCommitmentBasisPoints,
uint256 _minInvestment,
uint256 _minDuration
) external;
function pay(uint _currencyValue) external payable;
function pay(uint256 _currencyValue) external payable;
function totalSupply() external view returns (uint256);
function buybackReserve() external view returns (uint256);
function feeBasisPoints() external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function close() external;
}
function stopAndTransferReserve(address payable _recipient) external;
function isStopped() external view returns (bool);
}
Loading

0 comments on commit bd4338f

Please sign in to comment.