Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# MAINNET
# ETH MAINNET
MAINNET_URL = https://eth-mainnet.g.alchemy.com/v2/1234123412341234
MAINNET_PRIVATEKEY= 12341234123412341234123412341234

Expand All @@ -14,10 +14,19 @@ TENDERLY_PRIVATEKEY =
# ETHERSCAN APIY KEY
ETHERSCAN_API_KEY = ETHERSCANAPIKEYETHERSCANAPIKEY

# TESTNET
# STORY MAINNET
STORY_URL_MAINNET = http://
SAFE_MULTISIG_MAINNET =
SAFE_PROPOSER_MAINNET_ADDRESS =
SAFE_PROPOSER_MAINNET_PRIVATE_KEY =

# STORY TESTNET
STORY_URL = http://
STORY_CHAINID = 1315
STORY_PRIVATEKEY =
STORY_USER1 =
STORY_USER2 =
STORY_ERC721 =
SAFE_MULTISIG_AENEID =
SAFE_PROPOSER_AENEID_ADDRESS =
SAFE_PROPOSER_AENEID_PRIVATE_KEY =
1 change: 1 addition & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import "hardhat-contract-sizer" // npx hardhat size-contracts
import "solidity-coverage"
import "solidity-docgen"
import "@nomicfoundation/hardhat-chai-matchers"
import "./script/hardhat/utils/safePropose"

require("dotenv").config()

Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@
"dependencies": {
"@openzeppelin/contracts": "5.2.0",
"@openzeppelin/contracts-upgradeable": "5.2.0",
"@safe-global/api-kit": "^3.0.1",
"@safe-global/protocol-kit": "^6.0.3",
"@safe-global/types-kit": "^2.0.1",
"erc6551": "^0.3.1",
"solady": "^0.0.281"
}
Expand Down
15 changes: 9 additions & 6 deletions script/foundry/utils/JsonBatchTxHelper.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ contract JsonBatchTxHelper is Script {
uint256 value;
bytes data;
uint8 operation;
string txType; // schedule, execute, cancel
}

Transaction[] private transactions;
Expand All @@ -25,12 +26,13 @@ contract JsonBatchTxHelper is Script {
chainId = (block.chainid).toString();
}

function _writeTx(address _to, uint256 _value, bytes memory _data) internal {
function _writeTx(address _to, uint256 _value, bytes memory _data, string memory _type) internal {
transactions.push(Transaction({
to: _to,
value: _value,
data: _data,
operation: 0
operation: 0,
txType: _type
}));
console2.log("Added tx to ", _to);
console2.log("Value: ", _value);
Expand All @@ -39,18 +41,19 @@ contract JsonBatchTxHelper is Script {
console2.log("Operation: 0");
}

function _writeBatchTxsOutput(string memory _action) internal {
function _writeBatchTxsOutput(string memory _action, string memory _type) internal {
uint256 txCounter;
string memory json = "[";
for (uint i = 0; i < transactions.length; i++) {
if (i > 0) {
json = string(abi.encodePacked(json, ","));
}
if (keccak256(abi.encodePacked(transactions[i].txType)) != keccak256(abi.encodePacked(_type))) continue;
if (txCounter > 0) json = string(abi.encodePacked(json, ","));
json = string(abi.encodePacked(json, "{"));
json = string(abi.encodePacked(json, '"to":"', vm.toString(transactions[i].to), '",'));
json = string(abi.encodePacked(json, '"value":', vm.toString(transactions[i].value), ','));
json = string(abi.encodePacked(json, '"data":"', vm.toString(transactions[i].data), '",'));
json = string(abi.encodePacked(json, '"operation":', vm.toString(transactions[i].operation)));
json = string(abi.encodePacked(json, "}"));
txCounter++;
}
json = string(abi.encodePacked(json, "]"));

Expand Down
12 changes: 6 additions & 6 deletions script/foundry/utils/upgrades/TxGenerator.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ abstract contract TxGenerator is Script, JsonDeploymentHandler, JsonBatchTxHelpe

_generateActions();

_writeBatchTxsOutput(string.concat("schedule", "-", fromVersion, "-to-", toVersion)); // JsonBatchTxHelper.s.sol
_writeBatchTxsOutput(string.concat("execute", "-", fromVersion, "-to-", toVersion)); // JsonBatchTxHelper.s.sol
_writeBatchTxsOutput(string.concat("cancel", "-", fromVersion, "-to-", toVersion)); // JsonBatchTxHelper.s.sol
_writeBatchTxsOutput(string.concat("schedule", "-", fromVersion, "-to-", toVersion), "schedule"); // JsonBatchTxHelper.s.sol
_writeBatchTxsOutput(string.concat("execute", "-", fromVersion, "-to-", toVersion), "execute"); // JsonBatchTxHelper.s.sol
_writeBatchTxsOutput(string.concat("cancel", "-", fromVersion, "-to-", toVersion), "cancel"); // JsonBatchTxHelper.s.sol
}

function _generateActions() internal virtual;
Expand All @@ -96,7 +96,7 @@ abstract contract TxGenerator is Script, JsonDeploymentHandler, JsonBatchTxHelpe
bytes memory data = _getExecutionData(key, p);
if (data.length == 0) revert("No data to schedule");

_writeTx(address(accessManager), 0, abi.encodeCall(AccessManager.schedule, (p.proxy, data, 0)));
_writeTx(address(accessManager), 0, abi.encodeCall(AccessManager.schedule, (p.proxy, data, 0)), "schedule");

console2.log("--------------------");
}
Expand All @@ -116,7 +116,7 @@ abstract contract TxGenerator is Script, JsonDeploymentHandler, JsonBatchTxHelpe
console2.log("Execute scheduled tx");
console2.logBytes(data);

_writeTx(address(accessManager), 0, abi.encodeCall(AccessManager.execute, (p.proxy, data)));
_writeTx(address(accessManager), 0, abi.encodeCall(AccessManager.execute, (p.proxy, data)), "execute");
}

function _generateCancelTx(string memory key) internal {
Expand All @@ -130,7 +130,7 @@ abstract contract TxGenerator is Script, JsonDeploymentHandler, JsonBatchTxHelpe
bytes memory data = _getExecutionData(key, p);
if (data.length == 0) revert("No data to schedule");

_writeTx(address(accessManager), 0, abi.encodeCall(AccessManager.cancel, (deployer, p.proxy, data)));
_writeTx(address(accessManager), 0, abi.encodeCall(AccessManager.cancel, (deployer, p.proxy, data)), "cancel");

console2.log("--------------------");
}
Expand Down
58 changes: 58 additions & 0 deletions script/hardhat/utils/safePropose.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import SafeApiKit from '@safe-global/api-kit'
import Safe from '@safe-global/protocol-kit'
import {
MetaTransactionData,
OperationType
} from '@safe-global/types-kit'

require("dotenv").config()

task("safe-propose", "Propose a Safe transaction")
.addParam("chainid", "The chainId of the Safe")
.addParam("operation", "The operation type: schedule, execute or cancel")
.addParam("previousversion", "The previous version")
.addParam("newversion", "The next version")
.setAction(async (taskArgs, hre) => {
const chainId = parseInt(taskArgs.chainid)
if (chainId !== Number(process.env.STORY_CHAINID) && chainId !== Number(process.env.STORY_CHAINID_MAINNET)) {
throw new Error('Invalid chainId')
}

const RPC_URL = chainId === Number(process.env.STORY_CHAINID_MAINNET) ? process.env.STORY_URL_MAINNET : process.env.STORY_URL
const SAFE_ADDRESS = chainId === Number(process.env.STORY_CHAINID_MAINNET) ? process.env.SAFE_MULTISIG_MAINNET_ADDRESS : process.env.SAFE_MULTISIG_AENEID_ADDRESS
const SAFE_PROPOSER_ADDRESS = chainId === Number(process.env.STORY_CHAINID_MAINNET) ? process.env.SAFE_PROPOSER_MAINNET_ADDRESS : process.env.SAFE_PROPOSER_AENEID_ADDRESS
const SAFE_PROPOSER_PRIVATE_KEY = chainId === Number(process.env.STORY_CHAINID_MAINNET) ? process.env.SAFE_PROPOSER_MAINNET_PRIVATE_KEY : process.env.SAFE_PROPOSER_AENEID_PRIVATE_KEY
const TX_SERVICE_URL = chainId === Number(process.env.STORY_CHAINID_MAINNET) ? 'https://transaction.safe.story.foundation/api' : 'https://transaction-testnet.safe.story.foundation/api'

const apiKit = new SafeApiKit({
chainId: BigInt(chainId),
txServiceUrl: TX_SERVICE_URL
})

const protocolKitOwner1 = await Safe.init({
provider: RPC_URL,
signer: SAFE_PROPOSER_PRIVATE_KEY,
safeAddress: SAFE_ADDRESS
})

// Import the txs file
const safeTransactionData: MetaTransactionData[] = require(`../../../deploy-out/${taskArgs.operation}-v${taskArgs.previousversion}-to-v${taskArgs.newversion}-${chainId}.json`)

const safeTransaction = await protocolKitOwner1.createTransaction({
transactions: safeTransactionData
})

const safeTxHash = await protocolKitOwner1.getTransactionHash(safeTransaction)
const signature = await protocolKitOwner1.signHash(safeTxHash)

// Propose transaction to the service
await apiKit.proposeTransaction({
safeAddress: SAFE_ADDRESS,
safeTransactionData: safeTransaction.data,
safeTxHash,
senderAddress: SAFE_PROPOSER_ADDRESS,
senderSignature: signature.data
})

console.log('Transaction successfully proposed')
})
Loading
Loading