Skip to content

Commit

Permalink
chore: deployment scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
kupermind committed Aug 28, 2024
1 parent f1c0575 commit a0437ed
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 5 deletions.
19 changes: 18 additions & 1 deletion contracts/KarmaProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ pragma solidity ^0.8.25;
/// @dev Zero implementation address.
error ZeroImplementationAddress();

/// @dev Zero karma data.
error ZeroKarmaData();

/// @dev Proxy initialization failed.
error InitializationFailed();

/*
* This is a Karma proxy contract.
* Proxy implementation is created based on the Universal Upgradeable Proxy Standard (UUPS) EIP-1822.
Expand All @@ -24,16 +30,27 @@ contract KarmaProxy {

/// @dev KarmaProxy constructor.
/// @param implementation Karma implementation address.
constructor(address implementation) {
/// @param karmaData Karma initialization data.
constructor(address implementation, bytes memory karmaData) {
// Check for the zero address, since the delegatecall works even with the zero one
if (implementation == address(0)) {
revert ZeroImplementationAddress();
}

// Check for the zero data
if (karmaData.length == 0) {
revert ZeroKarmaData();
}

// Store the karma implementation address
assembly {
sstore(KARMA_PROXY, implementation)
}
// Initialize proxy tokenomics storage
(bool success, ) = implementation.delegatecall(karmaData);
if (!success) {
revert InitializationFailed();
}
}

/// @dev Delegatecall to all the incoming data.
Expand Down
75 changes: 75 additions & 0 deletions scripts/deployment/deploy_04_karma.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*global process*/

const { ethers } = require("hardhat");
const { LedgerSigner } = require("@anders-t/ethers-ledger");

async function main() {
const fs = require("fs");
const globalsFile = "globals.json";
const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
let parsedData = JSON.parse(dataFromJSON);
const useLedger = parsedData.useLedger;
const derivationPath = parsedData.derivationPath;
const providerName = parsedData.providerName;
const gasPriceInGwei = parsedData.gasPriceInGwei;

let networkURL = parsedData.networkURL;
if (providerName === "polygon") {
if (!process.env.ALCHEMY_API_KEY_MATIC) {
console.log("set ALCHEMY_API_KEY_MATIC env variable");
}
networkURL += process.env.ALCHEMY_API_KEY_MATIC;
} else if (providerName === "polygonMumbai") {
if (!process.env.ALCHEMY_API_KEY_MUMBAI) {
console.log("set ALCHEMY_API_KEY_MUMBAI env variable");
return;
}
networkURL += process.env.ALCHEMY_API_KEY_MUMBAI;
}

const provider = new ethers.providers.JsonRpcProvider(networkURL);
const signers = await ethers.getSigners();

let EOA;
if (useLedger) {
EOA = new LedgerSigner(provider, derivationPath);
} else {
EOA = signers[0];
}
// EOA address
const deployer = await EOA.getAddress();
console.log("EOA is:", deployer);

// Transaction signing and execution
console.log("4. EOA to deploy Karma");
console.log("You are signing the following transaction: Karma.connect(EOA).deploy()");
const gasPrice = ethers.utils.parseUnits(gasPriceInGwei, "gwei");
Karma = await ethers.getContractFactory("AgentFactorySubscription");

Check failure on line 47 in scripts/deployment/deploy_04_karma.js

View workflow job for this annotation

GitHub Actions / build

'Karma' is not defined
const karma = await Karma.connect(EOA).deploy({ gasPrice });

Check failure on line 48 in scripts/deployment/deploy_04_karma.js

View workflow job for this annotation

GitHub Actions / build

'Karma' is not defined
const result = await karma.deployed();

// Transaction details
console.log("Contract deployment: Karma");
console.log("Contract address:", karma.address);
console.log("Transaction:", result.deployTransaction.hash);

// Wait for half a minute for the transaction completion
await new Promise(r => setTimeout(r, 30000));

// Writing updated parameters back to the JSON file
parsedData.karmaAddress = karma.address;
fs.writeFileSync(globalsFile, JSON.stringify(parsedData));

// Contract verification
if (parsedData.contractVerification) {
const execSync = require("child_process").execSync;
execSync("npx hardhat verify --network " + providerName + " " + karma.address, { encoding: "utf-8" });
}
}

main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
80 changes: 80 additions & 0 deletions scripts/deployment/deploy_05_karma_proxy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*global process*/

const { ethers } = require("hardhat");
const { LedgerSigner } = require("@anders-t/ethers-ledger");

async function main() {
const fs = require("fs");
const globalsFile = "globals.json";
const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
let parsedData = JSON.parse(dataFromJSON);
const useLedger = parsedData.useLedger;
const derivationPath = parsedData.derivationPath;
const providerName = parsedData.providerName;
const gasPriceInGwei = parsedData.gasPriceInGwei;
const karmaAddress = parsedData.karmaAddress;

let networkURL = parsedData.networkURL;
if (providerName === "polygon") {
if (!process.env.ALCHEMY_API_KEY_MATIC) {
console.log("set ALCHEMY_API_KEY_MATIC env variable");
}
networkURL += process.env.ALCHEMY_API_KEY_MATIC;
} else if (providerName === "polygonMumbai") {
if (!process.env.ALCHEMY_API_KEY_MUMBAI) {
console.log("set ALCHEMY_API_KEY_MUMBAI env variable");
return;
}
networkURL += process.env.ALCHEMY_API_KEY_MUMBAI;
}

const provider = new ethers.providers.JsonRpcProvider(networkURL);
const signers = await ethers.getSigners();

let EOA;
if (useLedger) {
EOA = new LedgerSigner(provider, derivationPath);
} else {
EOA = signers[0];
}
// EOA address
const deployer = await EOA.getAddress();
console.log("EOA is:", deployer);

// Assemble the karma proxy data
const karma = await ethers.getContractAt("Karma", karmaAddress);
const proxyData = karma.interface.encodeFunctionData("initialize", []);

// Transaction signing and execution
console.log("5. EOA to deploy Karma Proxy");
console.log("You are signing the following transaction: KarmaProxy.connect(EOA).deploy()");
const gasPrice = ethers.utils.parseUnits(gasPriceInGwei, "gwei");
KarmaProxy = await ethers.getContractFactory("KarmaProxy");

Check failure on line 52 in scripts/deployment/deploy_05_karma_proxy.js

View workflow job for this annotation

GitHub Actions / build

'KarmaProxy' is not defined
const karmaProxy = await KarmaProxy.connect(EOA).deploy(karmaAddress, proxyData, { gasPrice });

Check failure on line 53 in scripts/deployment/deploy_05_karma_proxy.js

View workflow job for this annotation

GitHub Actions / build

'KarmaProxy' is not defined
const result = await karmaProxy.deployed();

// Transaction details
console.log("Contract deployment: KarmaProxy");
console.log("Contract address:", karmaProxy.address);
console.log("Transaction:", result.deployTransaction.hash);

// Wait for half a minute for the transaction completion
await new Promise(r => setTimeout(r, 30000));

// Writing updated parameters back to the JSON file
parsedData.karmaProxyAddress = karmaProxy.address;
fs.writeFileSync(globalsFile, JSON.stringify(parsedData));

// Contract verification
if (parsedData.contractVerification) {
const execSync = require("child_process").execSync;
execSync("npx hardhat verify --constructor-args scripts/deployment/verify_05_karma_proxy.js --network " + providerName + " " + karmaProxy.address, { encoding: "utf-8" });
}
}

main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
82 changes: 82 additions & 0 deletions scripts/deployment/deploy_06_mech_marketplace.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*global process*/

const { ethers } = require("hardhat");
const { LedgerSigner } = require("@anders-t/ethers-ledger");

async function main() {
const fs = require("fs");
const globalsFile = "globals.json";
const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
let parsedData = JSON.parse(dataFromJSON);
const useLedger = parsedData.useLedger;
const derivationPath = parsedData.derivationPath;
const providerName = parsedData.providerName;
const gasPriceInGwei = parsedData.gasPriceInGwei;
const stakingFactoryAddress = parsedData.stakingFactoryAddress;
const karmaProxyAddress = parsedData.karmaProxyAddress;
const minResponseTimeout = parsedData.minResponseTimeout;

Check warning on line 17 in scripts/deployment/deploy_06_mech_marketplace.js

View workflow job for this annotation

GitHub Actions / build

'minResponseTimeout' is assigned a value but never used
const maxResponseTimeout = parsedData.maxResponseTimeout;

Check warning on line 18 in scripts/deployment/deploy_06_mech_marketplace.js

View workflow job for this annotation

GitHub Actions / build

'maxResponseTimeout' is assigned a value but never used

let networkURL = parsedData.networkURL;
if (providerName === "polygon") {
if (!process.env.ALCHEMY_API_KEY_MATIC) {
console.log("set ALCHEMY_API_KEY_MATIC env variable");
}
networkURL += process.env.ALCHEMY_API_KEY_MATIC;
} else if (providerName === "polygonMumbai") {
if (!process.env.ALCHEMY_API_KEY_MUMBAI) {
console.log("set ALCHEMY_API_KEY_MUMBAI env variable");
return;
}
networkURL += process.env.ALCHEMY_API_KEY_MUMBAI;
}

const provider = new ethers.providers.JsonRpcProvider(networkURL);
const signers = await ethers.getSigners();

let EOA;
if (useLedger) {
EOA = new LedgerSigner(provider, derivationPath);
} else {
EOA = signers[0];
}
// EOA address
const deployer = await EOA.getAddress();
console.log("EOA is:", deployer);

// Transaction signing and execution
console.log("6. EOA to deploy Mech Marketplace");
console.log("You are signing the following transaction: MechMarketplace.connect(EOA).deploy()");
const gasPrice = ethers.utils.parseUnits(gasPriceInGwei, "gwei");
const mechMarketplace = await MechMarketplace.connect(EOA).deploy(stakingFactoryAddress, karmaProxyAddress,

Check failure on line 51 in scripts/deployment/deploy_06_mech_marketplace.js

View workflow job for this annotation

GitHub Actions / build

'MechMarketplace' is not defined
{ gasPrice });
// In case when gas calculation is not working correctly on Arbitrum
//const gasLimit = 60000000;
//const mechMarketplace = await MechMarketplace.connect(EOA).deploy(stakingFactoryAddress, { gasLimit });
const result = await mechMarketplace.deployed();

// Transaction details
console.log("Contract deployment: MechMarketplace");
console.log("Contract address:", mechMarketplace.address);
console.log("Transaction:", result.deployTransaction.hash);

// Wait for half a minute for the transaction completion
await new Promise(r => setTimeout(r, 30000));

// Writing updated parameters back to the JSON file
parsedData.mechMarketplaceAddress = mechMarketplace.address;
fs.writeFileSync(globalsFile, JSON.stringify(parsedData));

// Contract verification
if (parsedData.contractVerification) {
const execSync = require("child_process").execSync;
execSync("npx hardhat verify --constructor-args scripts/deployment/verify_06_mech_marketplace.js --network " + providerName + " " + mechMarketplace.address, { encoding: "utf-8" });
}
}

main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
2 changes: 1 addition & 1 deletion scripts/deployment/globals_gnosis_mainnet.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"gnosis","networkURL": "https://rpc.gnosischain.com","gasPriceInGwei":"20","agentType":"subscription","baseURI":"https://gateway.autonolas.tech/ipfs/","agentRegistryName":"AI Agent Registry","agentRegistrySymbol":"AI-AGENT-V1","agentRegistryAddress":"0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA","agentFactoryAddress": "0x4be7A91e67be963806FeFA9C1FD6C53DfC358d94","agentMechAddress": "0x77af31de935740567cf4ff1986d04b2c964a786a","agentId":"6","price":"10000000000000000","agentHash":"0x59ec5386a145869a4c8d14a3df188b32da54f4ae70bf9002df00672dbf777ffc","agentFactorySubscriptionAddress":"0x910Ca843Cad6C050Faf3f84387879b2928D40370","agentMechSubscriptionAddress":"0x327E26bDF1CfEa50BFAe35643B23D5268E41F7F9","agentIdSubscription":"3","minCreditsPerRequest":"1","subscriptionNFTAddress":"0x80A9b55F8604acC26dF2Ac6e07F9dC5B0eAa05Ce","subscriptionTokenId":"0x0ea01d5de3b34e3792db825f2a5f5595c393c68b19fd5efdacd00fcc63a53483","agentHashSubscription":"0x59ec5386a145869a4c8d14a3df188b32da54f4ae70bf9002df00672dbf777ffc"}
{"contractVerification":true,"useLedger":true,"derivationPath":"m/44'/60'/2'/0/0","providerName":"gnosis","networkURL": "https://rpc.gnosischain.com","gasPriceInGwei":"20","agentType":"subscription","baseURI":"https://gateway.autonolas.tech/ipfs/","agentRegistryName":"AI Agent Registry","agentRegistrySymbol":"AI-AGENT-V1","agentRegistryAddress":"0xE49CB081e8d96920C38aA7AB90cb0294ab4Bc8EA","agentFactoryAddress": "0x4be7A91e67be963806FeFA9C1FD6C53DfC358d94","agentMechAddress": "0x77af31de935740567cf4ff1986d04b2c964a786a","agentId":"6","price":"10000000000000000","agentHash":"0x59ec5386a145869a4c8d14a3df188b32da54f4ae70bf9002df00672dbf777ffc","agentFactorySubscriptionAddress":"0x910Ca843Cad6C050Faf3f84387879b2928D40370","agentMechSubscriptionAddress":"0x327E26bDF1CfEa50BFAe35643B23D5268E41F7F9","agentIdSubscription":"3","minCreditsPerRequest":"1","subscriptionNFTAddress":"0x80A9b55F8604acC26dF2Ac6e07F9dC5B0eAa05Ce","subscriptionTokenId":"0x0ea01d5de3b34e3792db825f2a5f5595c393c68b19fd5efdacd00fcc63a53483","agentHashSubscription":"0x59ec5386a145869a4c8d14a3df188b32da54f4ae70bf9002df00672dbf777ffc","karmaAddress":"","karmaProxyAddress":"","stakingFactoryAddress": "0xb0228CA253A88Bc8eb4ca70BCAC8f87b381f4700","minResponseTimeout":"60","maxResponseTimeout":"300"}
11 changes: 11 additions & 0 deletions scripts/deployment/verify_05_karma_proxy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const fs = require("fs");
const globalsFile = "globals.json";
const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
const parsedData = JSON.parse(dataFromJSON);
const karmaAddress = parsedData.karmaAddress;
const proxyData = "0x8129fc1c"; // initialize()

module.exports = [
karmaAddress,
proxyData
];
15 changes: 15 additions & 0 deletions scripts/deployment/verify_06_mech_marketplace.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const fs = require("fs");
const globalsFile = "globals.json";
const dataFromJSON = fs.readFileSync(globalsFile, "utf8");
const parsedData = JSON.parse(dataFromJSON);
const stakingFactoryAddress = parsedData.stakingFactoryAddress;
const karmaProxyAddress = parsedData.karmaProxyAddress;
const minResponseTimeout = parsedData.minResponseTimeout;
const maxResponseTimeout = parsedData.maxResponseTimeout;

module.exports = [
stakingFactoryAddress,
karmaProxyAddress,
minResponseTimeout,
maxResponseTimeout
];
6 changes: 3 additions & 3 deletions test/AgentMech.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ describe("AgentMech", function () {
const karmaImplementation = await Karma.deploy();
await karmaImplementation.deployed();

// Initialize karma
const proxyData = karmaImplementation.interface.encodeFunctionData("initialize", []);
const KarmaProxy = await ethers.getContractFactory("KarmaProxy");
const karmaProxy = await KarmaProxy.deploy(karmaImplementation.address);
const karmaProxy = await KarmaProxy.deploy(karmaImplementation.address, proxyData);
await karmaProxy.deployed();

// Initilize karma
karma = await ethers.getContractAt("Karma", karmaProxy.address);
await karma.initialize();

const ServiceStakingMech = await ethers.getContractFactory("MockServiceStaking");
serviceStakingMech = await ServiceStakingMech.deploy();
Expand Down

0 comments on commit a0437ed

Please sign in to comment.