From 39b9d8c8daf78d4c630364bdf24744f90e21937c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?=
Date: Tue, 5 May 2026 13:28:02 +0000
Subject: [PATCH 1/9] fix(deploy): add explicit proxy kind and use async fs in
upgrade script
- Add kind: "transparent" to upgradeProxy call to match upgrade-token-staking.ts
and eliminate dependency on OZ manifest for proxy-type detection
- Remove unused deployer variable from getNamedAccounts destructuring
- Replace sync fs calls with fs.promises equivalents
- Wrap JSON.parse in try/catch
---
deploy/54_upgrade_token_staking_extended.ts | 22 +++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/deploy/54_upgrade_token_staking_extended.ts b/deploy/54_upgrade_token_staking_extended.ts
index 92e3967d..cdcb33fb 100644
--- a/deploy/54_upgrade_token_staking_extended.ts
+++ b/deploy/54_upgrade_token_staking_extended.ts
@@ -15,9 +15,8 @@ import { ethers, upgrades } from "hardhat"
* npx hardhat deploy --network sepolia --tags UpgradeTokenStaking
*/
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
- const { deployments, getNamedAccounts } = hre
+ const { deployments } = hre
const { log } = deployments
- const { deployer } = await getNamedAccounts()
if (hre.network.name !== "sepolia") {
log("Skipping TokenStaking upgrade (only for sepolia)")
@@ -31,11 +30,15 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
} else {
// 07_deploy_token_staking saves to TokenStaking.json in deployments dir
const deploymentPath = `deployments/${hre.network.name}/TokenStaking.json`
- if (!fs.existsSync(deploymentPath)) {
+ try {
+ await fs.promises.access(deploymentPath)
+ } catch {
log("TokenStaking not deployed, skipping upgrade")
return
}
- const deployment = JSON.parse(fs.readFileSync(deploymentPath, "utf8"))
+ const deployment = JSON.parse(
+ await fs.promises.readFile(deploymentPath, "utf8")
+ )
proxyAddress = deployment.address
}
@@ -57,6 +60,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
ExtendedTokenStaking,
{
constructorArgs: [T.address],
+ kind: "transparent",
}
)
await upgraded.deployed()
@@ -66,12 +70,18 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
// Update deployment JSON with new ABI (includes stake)
const implementationInterface = upgraded.interface
const jsonAbi = implementationInterface.format(ethers.utils.FormatTypes.json)
+ let parsedAbi: unknown[]
+ try {
+ parsedAbi = JSON.parse(jsonAbi as string) as unknown[]
+ } catch (e) {
+ throw new Error(`Failed to parse ABI from contract interface: ${e}`)
+ }
const tokenStakingDeployment = {
address: upgraded.address,
- abi: JSON.parse(jsonAbi as string),
+ abi: parsedAbi,
}
const deploymentsDir = `deployments/${hre.network.name}`
- fs.writeFileSync(
+ await fs.promises.writeFile(
`${deploymentsDir}/TokenStaking.json`,
JSON.stringify(tokenStakingDeployment, null, 2),
"utf8"
From 847bf54ca5d04b3aafe15f76fe4858521364b778 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?=
Date: Tue, 5 May 2026 13:28:16 +0000
Subject: [PATCH 2/9] fix(scripts): restrict env file permissions to owner-only
after write
Plaintext private keys written to .env.operator-N were world-readable
under the default umask. chmod 0600 limits access to the current user.
---
scripts/setup-new-staking-provider.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/scripts/setup-new-staking-provider.js b/scripts/setup-new-staking-provider.js
index 8292adfe..beb4ad76 100644
--- a/scripts/setup-new-staking-provider.js
+++ b/scripts/setup-new-staking-provider.js
@@ -71,6 +71,7 @@ OPERATOR_KEYSTORE_PATH="${path.resolve(operatorFilepath)}"
`;
await fs.promises.writeFile(envPath, envContent);
+ await fs.promises.chmod(envPath, 0o600);
console.log("=== New Staking Provider + Operator ===\n");
console.log("Staking provider address:", stakingProvider.address);
From 6429ca5a07e5d302251f4cac37346342bfb9966a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?=
Date: Tue, 5 May 2026 13:28:47 +0000
Subject: [PATCH 3/9] fix(scripts): avoid passing private keys as CLI args to
cast wallet address
Keys passed via --private-key are visible in /proc//cmdline and
ps aux during execution. Use ETH_PRIVATE_KEY env var instead, which
Foundry's cast reads without exposing it in the process table.
---
scripts/setup-multiple-operators.sh | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/scripts/setup-multiple-operators.sh b/scripts/setup-multiple-operators.sh
index 8d4e1a03..fd70c531 100755
--- a/scripts/setup-multiple-operators.sh
+++ b/scripts/setup-multiple-operators.sh
@@ -215,7 +215,7 @@ resolve_t_minter_private_key() {
return 0
fi
if [ -n "${T_MINTER_PRIVATE_KEY:-}" ]; then
- _mk_addr=$(cast wallet address --private-key "${T_MINTER_PRIVATE_KEY}")
+ _mk_addr=$(ETH_PRIVATE_KEY="${T_MINTER_PRIVATE_KEY}" cast wallet address)
if [ "$(normalize_addr "$_mk_addr")" = "$_t_owner_lc" ]; then
printf '%s' "${T_MINTER_PRIVATE_KEY}"
return 0
@@ -330,7 +330,7 @@ fi
# Sourcing .env.operator-* must not clobber the deployer key (stale files sometimes set CONTRACT_OWNER_*).
_DEPLOYER_ACCOUNT_PRIVATE_KEY="$CONTRACT_OWNER_ACCOUNT_PRIVATE_KEY"
-_deployer_addr=$(cast wallet address --private-key "$_DEPLOYER_ACCOUNT_PRIVATE_KEY")
+_deployer_addr=$(ETH_PRIVATE_KEY="$_DEPLOYER_ACCOUNT_PRIVATE_KEY" cast wallet address)
command -v python3 >/dev/null 2>&1 || {
echo "ERROR: python3 is required for --new (T balance checks and AUTO_FUND_T mint)." >&2
echo " Install python3 on the runner, then retry." >&2
@@ -371,7 +371,7 @@ for i in $(seq 1 "$N"); do
exit 1
fi
- _sp_derived=$(cast wallet address --private-key "$NEW_STAKING_PROVIDER_KEY")
+ _sp_derived=$(ETH_PRIVATE_KEY="$NEW_STAKING_PROVIDER_KEY" cast wallet address)
_sp_a=$(echo "$_sp_derived" | tr '[:upper:]' '[:lower:]')
_sp_b=$(echo "$NEW_STAKING_PROVIDER_ADDRESS" | tr '[:upper:]' '[:lower:]')
if [ "$_sp_a" != "$_sp_b" ]; then
From 7ed779ec36fdc8ab729af84207815c2a640cae94 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?=
Date: Tue, 5 May 2026 13:29:03 +0000
Subject: [PATCH 4/9] fix(deployments): restore mainnet TokenStaking.json to
correct ABI
The PR introduced a reformatted version that dropped 4 constructor
parameters (_keepStakingContract, _nucypherStakingContract,
_keepVendingMachine, _keepStake), leaving a 2-param ABI that does not
match the deployed contract at 0x01B67b...765dd7. Restore the original
6-param ABI from main so downstream tooling is not broken.
---
deployments/mainnet/TokenStaking.json | 1576 ++++++++++++++-----------
1 file changed, 907 insertions(+), 669 deletions(-)
diff --git a/deployments/mainnet/TokenStaking.json b/deployments/mainnet/TokenStaking.json
index 79c9dd16..043ce32a 100644
--- a/deployments/mainnet/TokenStaking.json
+++ b/deployments/mainnet/TokenStaking.json
@@ -2,1352 +2,1590 @@
"address": "0x01B67b1194C75264d06F808A921228a95C765dd7",
"abi": [
{
- "type": "constructor",
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "_token"
+ "internalType": "contract T",
+ "name": "_token",
+ "type": "address"
+ },
+ {
+ "internalType": "contract IKeepTokenStaking",
+ "name": "_keepStakingContract",
+ "type": "address"
+ },
+ {
+ "internalType": "contract INuCypherStakingEscrow",
+ "name": "_nucypherStakingContract",
+ "type": "address"
+ },
+ {
+ "internalType": "contract VendingMachine",
+ "name": "_keepVendingMachine",
+ "type": "address"
+ },
+ {
+ "internalType": "contract VendingMachine",
+ "name": "_nucypherVendingMachine",
+ "type": "address"
},
{
- "type": "address",
- "name": "_nucypherVendingMachine"
+ "internalType": "contract KeepStake",
+ "name": "_keepStake",
+ "type": "address"
}
- ]
+ ],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
},
{
- "type": "event",
"anonymous": false,
- "name": "ApplicationStatusChanged",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "application",
- "indexed": true
+ "type": "address"
},
{
- "type": "uint8",
+ "indexed": true,
+ "internalType": "enum TokenStaking.ApplicationStatus",
"name": "newStatus",
- "indexed": true
+ "type": "uint8"
}
- ]
+ ],
+ "name": "ApplicationStatusChanged",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "AuthorizationCeilingSet",
"inputs": [
{
- "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256",
"name": "ceiling",
- "indexed": false
+ "type": "uint256"
}
- ]
+ ],
+ "name": "AuthorizationCeilingSet",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "AuthorizationDecreaseApproved",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "stakingProvider",
- "indexed": true
+ "type": "address"
},
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "application",
- "indexed": true
+ "type": "address"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "fromAmount",
- "indexed": false
+ "type": "uint96"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "toAmount",
- "indexed": false
+ "type": "uint96"
}
- ]
+ ],
+ "name": "AuthorizationDecreaseApproved",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "AuthorizationDecreaseRequested",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "stakingProvider",
- "indexed": true
+ "type": "address"
},
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "application",
- "indexed": true
+ "type": "address"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "fromAmount",
- "indexed": false
+ "type": "uint96"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "toAmount",
- "indexed": false
+ "type": "uint96"
}
- ]
+ ],
+ "name": "AuthorizationDecreaseRequested",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "AuthorizationIncreased",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "stakingProvider",
- "indexed": true
+ "type": "address"
},
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "application",
- "indexed": true
+ "type": "address"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "fromAmount",
- "indexed": false
+ "type": "uint96"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "toAmount",
- "indexed": false
+ "type": "uint96"
}
- ]
+ ],
+ "name": "AuthorizationIncreased",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "AuthorizationInvoluntaryDecreased",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "stakingProvider",
- "indexed": true
+ "type": "address"
},
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "application",
- "indexed": true
+ "type": "address"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "fromAmount",
- "indexed": false
+ "type": "uint96"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "toAmount",
- "indexed": false
+ "type": "uint96"
},
{
- "type": "bool",
+ "indexed": true,
+ "internalType": "bool",
"name": "successfulCall",
- "indexed": true
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "AutoIncreaseToggled",
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider",
- "indexed": true
- },
- {
- "type": "bool",
- "name": "autoIncrease",
- "indexed": false
+ "type": "bool"
}
- ]
+ ],
+ "name": "AuthorizationInvoluntaryDecreased",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "DelegateChanged",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "delegator",
- "indexed": true
+ "type": "address"
},
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "fromDelegate",
- "indexed": true
+ "type": "address"
},
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "toDelegate",
- "indexed": true
+ "type": "address"
}
- ]
+ ],
+ "name": "DelegateChanged",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "DelegateVotesChanged",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "delegate",
- "indexed": true
+ "type": "address"
},
{
- "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256",
"name": "previousBalance",
- "indexed": false
+ "type": "uint256"
},
{
- "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256",
"name": "newBalance",
- "indexed": false
+ "type": "uint256"
}
- ]
+ ],
+ "name": "DelegateVotesChanged",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "GovernanceTransferred",
"inputs": [
{
- "type": "address",
+ "indexed": false,
+ "internalType": "address",
"name": "oldGovernance",
- "indexed": false
+ "type": "address"
},
{
- "type": "address",
+ "indexed": false,
+ "internalType": "address",
"name": "newGovernance",
- "indexed": false
+ "type": "address"
}
- ]
+ ],
+ "name": "GovernanceTransferred",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "MinimumStakeAmountSet",
"inputs": [
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "amount",
- "indexed": false
+ "type": "uint96"
}
- ]
+ ],
+ "name": "MinimumStakeAmountSet",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "NotificationRewardPushed",
"inputs": [
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "reward",
- "indexed": false
+ "type": "uint96"
}
- ]
+ ],
+ "name": "NotificationRewardPushed",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "NotificationRewardSet",
"inputs": [
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "reward",
- "indexed": false
+ "type": "uint96"
}
- ]
+ ],
+ "name": "NotificationRewardSet",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "NotificationRewardWithdrawn",
"inputs": [
{
- "type": "address",
+ "indexed": false,
+ "internalType": "address",
"name": "recipient",
- "indexed": false
+ "type": "address"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "amount",
- "indexed": false
+ "type": "uint96"
}
- ]
+ ],
+ "name": "NotificationRewardWithdrawn",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "NotifierRewarded",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "notifier",
- "indexed": true
+ "type": "address"
},
{
- "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256",
"name": "amount",
- "indexed": false
+ "type": "uint256"
}
- ]
+ ],
+ "name": "NotifierRewarded",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "oldOwner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "OwnerRefreshed",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "PanicButtonSet",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "application",
- "indexed": true
+ "type": "address"
},
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "panicButton",
- "indexed": true
+ "type": "address"
}
- ]
+ ],
+ "name": "PanicButtonSet",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "SlashingProcessed",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "caller",
- "indexed": true
+ "type": "address"
},
{
- "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256",
"name": "count",
- "indexed": false
+ "type": "uint256"
},
{
- "type": "uint256",
+ "indexed": false,
+ "internalType": "uint256",
"name": "tAmount",
- "indexed": false
+ "type": "uint256"
}
- ]
+ ],
+ "name": "SlashingProcessed",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint96",
+ "name": "penalty",
+ "type": "uint96"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint256",
+ "name": "rewardMultiplier",
+ "type": "uint256"
+ }
+ ],
+ "name": "StakeDiscrepancyPenaltySet",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "Staked",
"inputs": [
{
- "type": "uint8",
+ "indexed": true,
+ "internalType": "enum IStaking.StakeType",
"name": "stakeType",
- "indexed": true
+ "type": "uint8"
},
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "owner",
- "indexed": true
+ "type": "address"
},
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "stakingProvider",
- "indexed": true
+ "type": "address"
},
{
- "type": "address",
+ "indexed": false,
+ "internalType": "address",
"name": "beneficiary",
- "indexed": false
+ "type": "address"
},
{
- "type": "address",
+ "indexed": false,
+ "internalType": "address",
"name": "authorizer",
- "indexed": false
+ "type": "address"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "amount",
- "indexed": false
+ "type": "uint96"
}
- ]
+ ],
+ "name": "Staked",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "TokensSeized",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "stakingProvider",
- "indexed": true
+ "type": "address"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "amount",
- "indexed": false
+ "type": "uint96"
},
{
- "type": "bool",
+ "indexed": true,
+ "internalType": "bool",
"name": "discrepancy",
- "indexed": true
+ "type": "bool"
}
- ]
+ ],
+ "name": "TokensSeized",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "ToppedUp",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "stakingProvider",
- "indexed": true
+ "type": "address"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "amount",
- "indexed": false
+ "type": "uint96"
}
- ]
+ ],
+ "name": "ToppedUp",
+ "type": "event"
},
{
- "type": "event",
"anonymous": false,
- "name": "Unstaked",
"inputs": [
{
- "type": "address",
+ "indexed": true,
+ "internalType": "address",
"name": "stakingProvider",
- "indexed": true
+ "type": "address"
},
{
- "type": "uint96",
+ "indexed": false,
+ "internalType": "uint96",
"name": "amount",
- "indexed": false
+ "type": "uint96"
}
- ]
+ ],
+ "name": "Unstaked",
+ "type": "event"
},
{
- "type": "function",
- "name": "applicationInfo",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
+ "internalType": "address",
+ "name": "",
"type": "address"
}
],
+ "name": "applicationInfo",
"outputs": [
{
- "type": "uint8",
- "name": "status"
+ "internalType": "enum TokenStaking.ApplicationStatus",
+ "name": "status",
+ "type": "uint8"
},
{
- "type": "address",
- "name": "panicButton"
+ "internalType": "address",
+ "name": "panicButton",
+ "type": "address"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "applications",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
+ "internalType": "uint256",
+ "name": "",
"type": "uint256"
}
],
+ "name": "applications",
"outputs": [
{
+ "internalType": "address",
+ "name": "",
"type": "address"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "approveApplication",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "application"
+ "internalType": "address",
+ "name": "application",
+ "type": "address"
}
],
- "outputs": []
+ "name": "approveApplication",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "approveAuthorizationDecrease",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
}
],
+ "name": "approveAuthorizationDecrease",
"outputs": [
{
+ "internalType": "uint96",
+ "name": "",
"type": "uint96"
}
- ]
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "authorizationCeiling",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [],
+ "name": "authorizationCeiling",
"outputs": [
{
+ "internalType": "uint256",
+ "name": "",
"type": "uint256"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "authorizedStake",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
},
{
- "type": "address",
- "name": "application"
+ "internalType": "address",
+ "name": "application",
+ "type": "address"
}
],
+ "name": "authorizedStake",
"outputs": [
{
+ "internalType": "uint96",
+ "name": "",
"type": "uint96"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "checkpoints",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "account"
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
},
{
- "type": "uint32",
- "name": "pos"
+ "internalType": "uint32",
+ "name": "pos",
+ "type": "uint32"
}
],
+ "name": "checkpoints",
"outputs": [
{
- "type": "tuple",
- "name": "checkpoint",
"components": [
{
- "type": "uint32",
- "name": "fromBlock"
+ "internalType": "uint32",
+ "name": "fromBlock",
+ "type": "uint32"
},
{
- "type": "uint96",
- "name": "votes"
+ "internalType": "uint96",
+ "name": "votes",
+ "type": "uint96"
}
- ]
+ ],
+ "internalType": "struct Checkpoints.Checkpoint",
+ "name": "checkpoint",
+ "type": "tuple"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "delegateVoting",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
},
{
- "type": "address",
- "name": "delegatee"
+ "internalType": "address",
+ "name": "delegatee",
+ "type": "address"
}
],
- "outputs": []
+ "name": "delegateVoting",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "delegates",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "account"
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
}
],
+ "name": "delegates",
"outputs": [
{
+ "internalType": "address",
+ "name": "",
"type": "address"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "disableApplication",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "application"
+ "internalType": "address",
+ "name": "application",
+ "type": "address"
}
],
- "outputs": []
+ "name": "disableApplication",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "forceDecreaseAuthorization",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
},
{
- "type": "address",
- "name": "application"
+ "internalType": "address",
+ "name": "application",
+ "type": "address"
}
],
- "outputs": []
+ "name": "forceDecreaseAuthorization",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "forceUnstakeLegacy",
- "constant": false,
- "payable": false,
- "inputs": [
+ "inputs": [],
+ "name": "getApplicationsLength",
+ "outputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
}
],
- "outputs": []
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "forceUnstakeLegacy",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address[]",
- "name": "_stakingProviders"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "application",
+ "type": "address"
}
],
- "outputs": []
- },
- {
- "type": "function",
- "name": "getApplicationsLength",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [],
+ "name": "getAvailableToAuthorize",
"outputs": [
{
- "type": "uint256"
+ "internalType": "uint96",
+ "name": "availableTValue",
+ "type": "uint96"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "getAutoIncreaseFlag",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
+ },
+ {
+ "internalType": "enum IStaking.StakeType",
+ "name": "stakeTypes",
+ "type": "uint8"
}
],
+ "name": "getMinStaked",
"outputs": [
{
- "type": "bool"
- }
- ]
- },
- {
- "type": "function",
- "name": "getAvailableToAuthorize",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- },
- {
- "type": "address",
- "name": "application"
+ "internalType": "uint96",
+ "name": "",
+ "type": "uint96"
}
],
- "outputs": [
- {
- "type": "uint96",
- "name": "availableTValue"
- }
- ]
- },
- {
- "type": "function",
- "name": "getMinStaked",
- "constant": true,
"stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- },
- {
- "type": "uint8",
- "name": "stakeTypes"
- }
- ],
- "outputs": [
- {
- "type": "uint96"
- }
- ]
+ "type": "function"
},
{
- "type": "function",
- "name": "getPastTotalSupply",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
- "type": "uint256",
- "name": "blockNumber"
+ "internalType": "uint256",
+ "name": "blockNumber",
+ "type": "uint256"
}
],
+ "name": "getPastTotalSupply",
"outputs": [
{
+ "internalType": "uint96",
+ "name": "",
"type": "uint96"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "getPastVotes",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "account"
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
},
{
- "type": "uint256",
- "name": "blockNumber"
+ "internalType": "uint256",
+ "name": "blockNumber",
+ "type": "uint256"
}
],
+ "name": "getPastVotes",
"outputs": [
{
+ "internalType": "uint96",
+ "name": "",
"type": "uint96"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "getSlashingQueueLength",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [],
+ "name": "getSlashingQueueLength",
"outputs": [
{
+ "internalType": "uint256",
+ "name": "",
"type": "uint256"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "getStartStakingTimestamp",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
}
],
+ "name": "getStartStakingTimestamp",
"outputs": [
{
+ "internalType": "uint256",
+ "name": "",
"type": "uint256"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "getVotes",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "account"
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
}
],
+ "name": "getVotes",
"outputs": [
{
+ "internalType": "uint96",
+ "name": "",
"type": "uint96"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "governance",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [],
+ "name": "governance",
"outputs": [
{
+ "internalType": "address",
+ "name": "",
"type": "address"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "increaseAuthorization",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
},
{
- "type": "address",
- "name": "application"
+ "internalType": "address",
+ "name": "application",
+ "type": "address"
},
{
- "type": "uint96",
- "name": "amount"
+ "internalType": "uint96",
+ "name": "amount",
+ "type": "uint96"
}
],
- "outputs": []
+ "name": "increaseAuthorization",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "initialize",
- "constant": false,
- "payable": false,
"inputs": [],
- "outputs": []
+ "name": "initialize",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "minTStakeAmount",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [],
+ "name": "minTStakeAmount",
"outputs": [
{
+ "internalType": "uint96",
+ "name": "",
"type": "uint96"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "notificationReward",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [],
+ "name": "notificationReward",
"outputs": [
{
+ "internalType": "uint256",
+ "name": "",
"type": "uint256"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "notifiersTreasury",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [],
+ "name": "notifiersTreasury",
"outputs": [
{
+ "internalType": "uint256",
+ "name": "",
"type": "uint256"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
+ }
+ ],
+ "name": "notifyKeepStakeDiscrepancy",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
+ }
+ ],
+ "name": "notifyNuStakeDiscrepancy",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "numCheckpoints",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "account"
+ "internalType": "address",
+ "name": "account",
+ "type": "address"
}
],
+ "name": "numCheckpoints",
"outputs": [
{
+ "internalType": "uint32",
+ "name": "",
"type": "uint32"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "pauseApplication",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "application"
+ "internalType": "address",
+ "name": "application",
+ "type": "address"
}
],
- "outputs": []
+ "name": "pauseApplication",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "processSlashing",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "uint256",
- "name": "count"
+ "internalType": "uint256",
+ "name": "count",
+ "type": "uint256"
}
],
- "outputs": []
+ "name": "processSlashing",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
+ "inputs": [
+ {
+ "internalType": "uint96",
+ "name": "reward",
+ "type": "uint96"
+ }
+ ],
"name": "pushNotificationReward",
- "constant": false,
- "payable": false,
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"inputs": [
{
- "type": "uint96",
- "name": "reward"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
}
],
- "outputs": []
+ "name": "refreshKeepStakeOwner",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "requestAuthorizationDecrease",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
},
{
- "type": "address",
- "name": "application"
+ "internalType": "address",
+ "name": "application",
+ "type": "address"
},
{
- "type": "uint96",
- "name": "amount"
+ "internalType": "uint96",
+ "name": "amount",
+ "type": "uint96"
}
],
- "outputs": []
+ "name": "requestAuthorizationDecrease",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "requestAuthorizationDecrease",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
}
],
- "outputs": []
+ "name": "requestAuthorizationDecrease",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "rolesOf",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
}
],
+ "name": "rolesOf",
"outputs": [
{
- "type": "address",
- "name": "owner"
+ "internalType": "address",
+ "name": "owner",
+ "type": "address"
},
{
- "type": "address",
- "name": "beneficiary"
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
},
{
- "type": "address",
- "name": "authorizer"
+ "internalType": "address",
+ "name": "authorizer",
+ "type": "address"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "seize",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "uint96",
- "name": "amount"
+ "internalType": "uint96",
+ "name": "amount",
+ "type": "uint96"
},
{
- "type": "uint256",
- "name": "rewardMultiplier"
+ "internalType": "uint256",
+ "name": "rewardMultiplier",
+ "type": "uint256"
},
{
- "type": "address",
- "name": "notifier"
+ "internalType": "address",
+ "name": "notifier",
+ "type": "address"
},
{
- "type": "address[]",
- "name": "_stakingProviders"
+ "internalType": "address[]",
+ "name": "_stakingProviders",
+ "type": "address[]"
}
],
- "outputs": []
+ "name": "seize",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "setAuthorizationCeiling",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "uint256",
- "name": "ceiling"
+ "internalType": "uint256",
+ "name": "ceiling",
+ "type": "uint256"
}
],
- "outputs": []
+ "name": "setAuthorizationCeiling",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "setMinimumStakeAmount",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "uint96",
- "name": "amount"
+ "internalType": "uint96",
+ "name": "amount",
+ "type": "uint96"
}
],
- "outputs": []
+ "name": "setMinimumStakeAmount",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "setNotificationReward",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "uint96",
- "name": "reward"
+ "internalType": "uint96",
+ "name": "reward",
+ "type": "uint96"
}
],
- "outputs": []
+ "name": "setNotificationReward",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "application",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "panicButton",
+ "type": "address"
+ }
+ ],
"name": "setPanicButton",
- "constant": false,
- "payable": false,
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"inputs": [
{
- "type": "address",
- "name": "application"
+ "internalType": "uint96",
+ "name": "penalty",
+ "type": "uint96"
},
{
- "type": "address",
- "name": "panicButton"
+ "internalType": "uint256",
+ "name": "rewardMultiplier",
+ "type": "uint256"
}
],
- "outputs": []
+ "name": "setStakeDiscrepancyPenalty",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "slash",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "uint96",
- "name": "amount"
+ "internalType": "uint96",
+ "name": "amount",
+ "type": "uint96"
},
{
- "type": "address[]",
- "name": "_stakingProviders"
+ "internalType": "address[]",
+ "name": "_stakingProviders",
+ "type": "address[]"
}
],
- "outputs": []
+ "name": "slash",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "slashingQueue",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [
{
+ "internalType": "uint256",
+ "name": "",
"type": "uint256"
}
],
+ "name": "slashingQueue",
"outputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
},
{
- "type": "uint96",
- "name": "amount"
+ "internalType": "uint96",
+ "name": "amount",
+ "type": "uint96"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "slashingQueueIndex",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
"inputs": [],
+ "name": "slashingQueueIndex",
"outputs": [
{
+ "internalType": "uint256",
+ "name": "",
"type": "uint256"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "stake",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
},
{
- "type": "address",
- "name": "beneficiary"
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
},
{
- "type": "address",
- "name": "authorizer"
+ "internalType": "address",
+ "name": "authorizer",
+ "type": "address"
},
{
- "type": "uint96",
- "name": "amount"
+ "internalType": "uint96",
+ "name": "amount",
+ "type": "uint96"
}
],
- "outputs": []
+ "name": "stake",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "stakedNu",
- "constant": true,
+ "inputs": [],
+ "name": "stakeDiscrepancyPenalty",
+ "outputs": [
+ {
+ "internalType": "uint96",
+ "name": "",
+ "type": "uint96"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "stakeDiscrepancyRewardMultiplier",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
"stateMutability": "view",
- "payable": false,
+ "type": "function"
+ },
+ {
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
}
],
- "outputs": [
+ "name": "stakeKeep",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
+ },
{
- "type": "uint256",
- "name": "nuAmount"
+ "internalType": "address payable",
+ "name": "beneficiary",
+ "type": "address"
+ },
+ {
+ "internalType": "address",
+ "name": "authorizer",
+ "type": "address"
}
- ]
+ ],
+ "name": "stakeNu",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "stakes",
- "constant": true,
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
+ }
+ ],
+ "name": "stakedNu",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "nuAmount",
+ "type": "uint256"
+ }
+ ],
"stateMutability": "view",
- "payable": false,
+ "type": "function"
+ },
+ {
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
}
],
+ "name": "stakes",
"outputs": [
{
- "type": "uint96",
- "name": "tStake"
+ "internalType": "uint96",
+ "name": "tStake",
+ "type": "uint96"
},
{
- "type": "uint96",
- "name": "keepInTStake"
+ "internalType": "uint96",
+ "name": "keepInTStake",
+ "type": "uint96"
},
{
- "type": "uint96",
- "name": "nuInTStake"
+ "internalType": "uint96",
+ "name": "nuInTStake",
+ "type": "uint96"
}
- ]
+ ],
+ "stateMutability": "view",
+ "type": "function"
},
{
- "type": "function",
- "name": "toggleAutoAuthorizationIncrease",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
+ },
+ {
+ "internalType": "uint96",
+ "name": "amount",
+ "type": "uint96"
}
],
- "outputs": []
+ "name": "topUp",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "topUp",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
- },
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
+ }
+ ],
+ "name": "topUpKeep",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
{
- "type": "uint96",
- "name": "amount"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
}
],
- "outputs": []
+ "name": "topUpNu",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "transferGovernance",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "newGuvnor"
+ "internalType": "address",
+ "name": "newGuvnor",
+ "type": "address"
}
],
- "outputs": []
+ "name": "transferGovernance",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "unstakeAll",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
}
],
- "outputs": []
+ "name": "unstakeAll",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "unstakeKeep",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
}
],
- "outputs": []
+ "name": "unstakeKeep",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "unstakeNu",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
+ },
+ {
+ "internalType": "uint96",
+ "name": "amount",
+ "type": "uint96"
}
],
- "outputs": []
+ "name": "unstakeNu",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "unstakeT",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "stakingProvider"
+ "internalType": "address",
+ "name": "stakingProvider",
+ "type": "address"
},
{
- "type": "uint96",
- "name": "amount"
+ "internalType": "uint96",
+ "name": "amount",
+ "type": "uint96"
}
],
- "outputs": []
+ "name": "unstakeT",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
},
{
- "type": "function",
- "name": "withdrawNotificationReward",
- "constant": false,
- "payable": false,
"inputs": [
{
- "type": "address",
- "name": "recipient"
+ "internalType": "address",
+ "name": "recipient",
+ "type": "address"
},
{
- "type": "uint96",
- "name": "amount"
+ "internalType": "uint96",
+ "name": "amount",
+ "type": "uint96"
}
],
- "outputs": []
+ "name": "withdrawNotificationReward",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
}
]
}
\ No newline at end of file
From d893ec31fc41390c09416442e83161c8a3f46f60 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?=
Date: Tue, 5 May 2026 13:30:12 +0000
Subject: [PATCH 5/9] fix(scripts): deduplicate cast_send_ok into shared lib
run-new-operator-setup.sh had a cast_send_ok without retry logic;
setup-multiple-operators.sh had one with exponential backoff. Nonce-lag
errors that were handled transparently in the multi-operator script would
fail silently in the single-operator script.
Extract the full retry implementation into scripts/lib/cast-helpers.sh
and source it from both scripts.
---
scripts/lib/cast-helpers.sh | 55 ++++++++++++++++++++++++++++
scripts/run-new-operator-setup.sh | 28 +++------------
scripts/setup-multiple-operators.sh | 56 +++--------------------------
3 files changed, 63 insertions(+), 76 deletions(-)
create mode 100644 scripts/lib/cast-helpers.sh
diff --git a/scripts/lib/cast-helpers.sh b/scripts/lib/cast-helpers.sh
new file mode 100644
index 00000000..27e42e3c
--- /dev/null
+++ b/scripts/lib/cast-helpers.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# Shared cast helpers for operator setup scripts.
+
+# cast send often exits 0 even when the mined tx reverts. Abort if receipt
+# status != 1 so dependent steps (increaseAuthorization, joinSortitionPool)
+# are not attempted after a silent revert.
+#
+# Public RPCs (e.g. Alchemy) sometimes return "nonce too low" when the node
+# has not caught up to the previous tx. Retry with exponential backoff.
+# Override max retries via CAST_SEND_MAX_RETRIES (default 10).
+cast_send_ok() {
+ local out tx st attempts max sleep_s
+ local _pk="${ETH_PRIVATE_KEY:-}"
+ if [ -z "$_pk" ]; then
+ echo "cast_send_ok: ETH_PRIVATE_KEY is unset or empty" >&2
+ return 1
+ fi
+ attempts=1
+ max="${CAST_SEND_MAX_RETRIES:-10}"
+ sleep_s=1
+ while true; do
+ if out=$(cast send "$@" --private-key "$_pk" 2>&1); then
+ break
+ fi
+ if echo "$out" | grep -qiE 'nonce too low|nonce has already been used|transaction already|already known'; then
+ if [ "$attempts" -ge "$max" ]; then
+ echo "$out" >&2
+ echo "cast_send_ok: exhausted $max retries for nonce/RPC race" >&2
+ return 1
+ fi
+ echo "cast_send_ok: transient RPC/nonce error (attempt $attempts/$max), retrying in ${sleep_s}s..." >&2
+ sleep "$sleep_s"
+ attempts=$((attempts + 1))
+ if [ "$sleep_s" -lt 16 ]; then
+ sleep_s=$((sleep_s * 2))
+ fi
+ continue
+ fi
+ echo "$out"
+ return 1
+ done
+ echo "$out"
+ tx=$(echo "$out" | awk '/^[[:space:]]*transactionHash[[:space:]]/ {print $2; exit}')
+ if [ -z "$tx" ] || [ "${#tx}" -ne 66 ] || [ "${tx#0x}" = "$tx" ]; then
+ echo "cast_send_ok: could not parse top-level transactionHash from cast output (got: ${tx:-empty})" >&2
+ return 1
+ fi
+ st=$(cast receipt "$tx" --rpc-url "$CHAIN_API_URL" | awk '/^status[[:space:]]+/ {print $2; exit}')
+ if [ "$st" != "1" ]; then
+ echo "cast_send_ok: transaction reverted on-chain (status=$st): $tx" >&2
+ echo "If this was stake(), fix that before increaseAuthorization -- otherwise you see \"Not authorizer\"." >&2
+ return 1
+ fi
+ return 0
+}
diff --git a/scripts/run-new-operator-setup.sh b/scripts/run-new-operator-setup.sh
index 4526ac53..19494199 100644
--- a/scripts/run-new-operator-setup.sh
+++ b/scripts/run-new-operator-setup.sh
@@ -23,8 +23,11 @@
#
set -e
-# Contract addresses (from tbtc-v2 deployments)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+# shellcheck source=scripts/lib/cast-helpers.sh
+source "$SCRIPT_DIR/lib/cast-helpers.sh"
+
+# Contract addresses (from tbtc-v2 deployments)
DEPLOYMENTS="$(cd "$SCRIPT_DIR/../../tbtc-v2/solidity/deployments/sepolia" && pwd)"
TOKEN_STAKING="$(jq -re '.address' "$DEPLOYMENTS/TokenStaking.json")"
RANDOM_BEACON="$(jq -re '.address' "$DEPLOYMENTS/RandomBeacon.json")"
@@ -51,8 +54,6 @@ SP_KEY="$NEW_STAKING_PROVIDER_KEY"
OP="$NEW_OPERATOR_ADDRESS"
OP_KEY="$NEW_OPERATOR_KEY"
-# Use ETH_PRIVATE_KEY env var so keys are not passed as CLI arguments
-# (--private-key exposes the key in ps aux and shell history)
_sp_cast_send_ok() {
ETH_PRIVATE_KEY="$SP_KEY" cast_send_ok "$@"
}
@@ -60,27 +61,6 @@ _op_cast_send_ok() {
ETH_PRIVATE_KEY="$OP_KEY" cast_send_ok "$@"
}
-cast_send_ok() {
- local out tx st
- out=$(cast send "$@" 2>&1) || {
- echo "$out"
- return 1
- }
- echo "$out"
- tx=$(echo "$out" | awk '/^[[:space:]]*transactionHash[[:space:]]/ {print $2; exit}')
- if [ -z "$tx" ] || [ "${#tx}" -ne 66 ] || [ "${tx#0x}" = "$tx" ]; then
- echo "cast_send_ok: could not parse top-level transactionHash from cast output (got: ${tx:-empty})" >&2
- return 1
- fi
- st=$(cast receipt "$tx" --rpc-url "$CHAIN_API_URL" | awk '/^status[[:space:]]+/ {print $2; exit}')
- if [ "$st" != "1" ]; then
- echo "cast_send_ok: transaction reverted on-chain (status=$st): $tx" >&2
- echo "If this was stake(), fix that before increaseAuthorization — otherwise you see \"Not authorizer\"." >&2
- return 1
- fi
- return 0
-}
-
echo "=== Step 1: Approve TokenStaking to spend T ==="
_sp_cast_send_ok $T_TOKEN "approve(address,uint256)" $TOKEN_STAKING $AMOUNT_80K \
--rpc-url $CHAIN_API_URL
diff --git a/scripts/setup-multiple-operators.sh b/scripts/setup-multiple-operators.sh
index fd70c531..3ddd5954 100755
--- a/scripts/setup-multiple-operators.sh
+++ b/scripts/setup-multiple-operators.sh
@@ -38,6 +38,10 @@
#
set -e
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+# shellcheck source=scripts/lib/cast-helpers.sh
+source "$SCRIPT_DIR/lib/cast-helpers.sh"
+
# CRLF or stray whitespace in .env / vault-sourced vars breaks `cast` ("Failed to decode private key").
strip_secret() {
local s="$1"
@@ -107,58 +111,6 @@ T_MINTER_PRIVATE_KEY=$(strip_secret "${T_MINTER_PRIVATE_KEY:-}")
: "${CHAIN_API_URL:?Set CHAIN_API_URL in .env}"
-# cast send often exits 0 even when the mined tx reverts. Abort if receipt status != 1 so we do not
-# run increaseAuthorization next (that fails with "Not authorizer" when stake never succeeded).
-#
-# Public RPCs (e.g. Alchemy) sometimes return "nonce too low" when the node has not caught up to the
-# previous tx yet. Retry with backoff (override via CAST_SEND_MAX_RETRIES).
-cast_send_ok() {
- local out tx st attempts max sleep_s
- local _pk="${ETH_PRIVATE_KEY:-}"
- if [ -z "$_pk" ]; then
- echo "cast_send_ok: ETH_PRIVATE_KEY is unset or empty" >&2
- return 1
- fi
- attempts=1
- max="${CAST_SEND_MAX_RETRIES:-10}"
- sleep_s=1
- while true; do
- if out=$(cast send "$@" --private-key "$_pk" 2>&1); then
- break
- fi
- if echo "$out" | grep -qiE 'nonce too low|nonce has already been used|transaction already|already known'; then
- if [ "$attempts" -ge "$max" ]; then
- echo "$out" >&2
- echo "cast_send_ok: exhausted $max retries for nonce/RPC race" >&2
- return 1
- fi
- echo "cast_send_ok: transient RPC/nonce error (attempt $attempts/$max), retrying in ${sleep_s}s..." >&2
- sleep "$sleep_s"
- attempts=$((attempts + 1))
- if [ "$sleep_s" -lt 16 ]; then
- sleep_s=$((sleep_s * 2))
- fi
- continue
- fi
- echo "$out"
- return 1
- done
- echo "$out"
- # Match only the receipt line; do not use /transactionHash/ — logs JSON also contains "transactionHash".
- tx=$(echo "$out" | awk '/^[[:space:]]*transactionHash[[:space:]]/ {print $2; exit}')
- if [ -z "$tx" ] || [ "${#tx}" -ne 66 ] || [ "${tx#0x}" = "$tx" ]; then
- echo "cast_send_ok: could not parse top-level transactionHash from cast output (got: ${tx:-empty})" >&2
- return 1
- fi
- st=$(cast receipt "$tx" --rpc-url "$CHAIN_API_URL" | awk '/^status[[:space:]]+/ {print $2; exit}')
- if [ "$st" != "1" ]; then
- echo "cast_send_ok: transaction reverted on-chain (status=$st): $tx" >&2
- echo "If this was stake(), fix that before increaseAuthorization — otherwise you see \"Not authorizer\"." >&2
- return 1
- fi
- return 0
-}
-
compute_t_shortfall_between() {
python3 -c "
import sys
From ac687bc720c95c5c2c19b582c1b1007cb239b2f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?=
Date: Tue, 5 May 2026 13:30:26 +0000
Subject: [PATCH 6/9] fix(scripts): list keystore addresses without attempting
decryption
--list was calling fromEncryptedJson with an empty password to extract
the address. Keystore JSON contains an unencrypted "address" field;
reading it directly avoids spurious decryption errors for keystores
with real passwords and removes the dependency on the ethers decrypt path.
---
scripts/get-operator-key.js | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/scripts/get-operator-key.js b/scripts/get-operator-key.js
index b29e065c..4916f39c 100644
--- a/scripts/get-operator-key.js
+++ b/scripts/get-operator-key.js
@@ -25,11 +25,12 @@ async function main() {
path.join(dir, file),
"utf8"
);
- const json = content.split("\n")[0]; // some files have extra content
- if (json.startsWith("{")) {
- const wallet = await ethers.Wallet.fromEncryptedJson(json, "");
- console.log(file, "->", wallet.address);
- }
+ // Keystore JSON has an unencrypted "address" field -- no decryption needed.
+ const parsed = JSON.parse(content);
+ const addr = parsed.address
+ ? `0x${parsed.address.replace(/^0x/, "")}`
+ : "(no address field)";
+ console.log(file, "->", addr);
} catch (e) {
console.log(file, "-> error:", e.message);
}
From 7220f5987f4c09ee979fe0efe1b347e821271293 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?=
Date: Tue, 5 May 2026 13:30:47 +0000
Subject: [PATCH 7/9] fix(scripts): harden fund-new-operator.sh
- Remove hardcoded fallback T token address; fail loudly with a clear
error if T.json is missing rather than silently using a stale address
- Quote all shell variables in the cast send call to prevent word
splitting on RPC URLs that include API key query parameters
---
scripts/fund-new-operator.sh | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/scripts/fund-new-operator.sh b/scripts/fund-new-operator.sh
index 3470cecd..155ba2d6 100755
--- a/scripts/fund-new-operator.sh
+++ b/scripts/fund-new-operator.sh
@@ -18,11 +18,12 @@ set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
T_JSON="$REPO_ROOT/tbtc-v2/solidity/deployments/sepolia/T.json"
-if [ -f "$T_JSON" ]; then
- T_TOKEN="$(jq -re '.address' "$T_JSON")"
-else
- T_TOKEN="0x60185Ef360A2a54D022718a8D95Ff3a23dE01a2d"
+if [ ! -f "$T_JSON" ]; then
+ echo "ERROR: T.json not found at $T_JSON" >&2
+ echo " Ensure tbtc-v2 is checked out at $REPO_ROOT/tbtc-v2 and Sepolia deployments exist." >&2
+ exit 1
fi
+T_TOKEN="$(jq -re '.address' "$T_JSON")"
AMOUNT_80K="$(cast to-wei 80000)"
cd "$SCRIPT_DIR/.."
@@ -42,8 +43,8 @@ fi
echo "=== Transfer 80,000 T to staking provider ==="
ETH_PRIVATE_KEY="$CONTRACT_OWNER_ACCOUNT_PRIVATE_KEY" \
- cast send $T_TOKEN "transfer(address,uint256)" $NEW_STAKING_PROVIDER_ADDRESS $AMOUNT_80K \
- --rpc-url $CHAIN_API_URL
+ cast send "$T_TOKEN" "transfer(address,uint256)" "$NEW_STAKING_PROVIDER_ADDRESS" "$AMOUNT_80K" \
+ --rpc-url "$CHAIN_API_URL"
echo ""
echo "=== Sepolia ETH ==="
From ff982cacf78044f05c080bb056376200fde622d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Ros=C5=82aniec?=
Date: Tue, 5 May 2026 13:32:08 +0000
Subject: [PATCH 8/9] fix(deploy): remove root-level TokenStaking.json write
07_deploy_token_staking.ts was writing to both the root TokenStaking.json
and deployments//TokenStaking.json. After the upgrade script runs,
only the network-specific file is updated, leaving the root file with a
stale ABI. Write only to deployments// and delete the root-level
artifact that was previously committed.
Also fix pre-existing issues in the file: use strict equality, static
import for fs, const for jsonAbi, async fs.promises, and try/catch around
JSON.parse.
---
TokenStaking.json | 1120 -----------------------------
deploy/07_deploy_token_staking.ts | 31 +-
2 files changed, 14 insertions(+), 1137 deletions(-)
delete mode 100644 TokenStaking.json
diff --git a/TokenStaking.json b/TokenStaking.json
deleted file mode 100644
index 3ca2f392..00000000
--- a/TokenStaking.json
+++ /dev/null
@@ -1,1120 +0,0 @@
-{
- "address": "0x3245B1a2dc82D02F7e159CA5ef14B6e35585779a",
- "abi": [
- {
- "type": "constructor",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "_token"
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "ApplicationStatusChanged",
- "inputs": [
- {
- "type": "address",
- "name": "application",
- "indexed": true
- },
- {
- "type": "uint8",
- "name": "newStatus",
- "indexed": true
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "AuthorizationCeilingSet",
- "inputs": [
- {
- "type": "uint256",
- "name": "ceiling",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "AuthorizationDecreaseApproved",
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider",
- "indexed": true
- },
- {
- "type": "address",
- "name": "application",
- "indexed": true
- },
- {
- "type": "uint96",
- "name": "fromAmount",
- "indexed": false
- },
- {
- "type": "uint96",
- "name": "toAmount",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "AuthorizationDecreaseRequested",
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider",
- "indexed": true
- },
- {
- "type": "address",
- "name": "application",
- "indexed": true
- },
- {
- "type": "uint96",
- "name": "fromAmount",
- "indexed": false
- },
- {
- "type": "uint96",
- "name": "toAmount",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "AuthorizationIncreased",
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider",
- "indexed": true
- },
- {
- "type": "address",
- "name": "application",
- "indexed": true
- },
- {
- "type": "uint96",
- "name": "fromAmount",
- "indexed": false
- },
- {
- "type": "uint96",
- "name": "toAmount",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "AuthorizationInvoluntaryDecreased",
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider",
- "indexed": true
- },
- {
- "type": "address",
- "name": "application",
- "indexed": true
- },
- {
- "type": "uint96",
- "name": "fromAmount",
- "indexed": false
- },
- {
- "type": "uint96",
- "name": "toAmount",
- "indexed": false
- },
- {
- "type": "bool",
- "name": "successfulCall",
- "indexed": true
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "AutoIncreaseToggled",
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider",
- "indexed": true
- },
- {
- "type": "bool",
- "name": "autoIncrease",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "DelegateChanged",
- "inputs": [
- {
- "type": "address",
- "name": "delegator",
- "indexed": true
- },
- {
- "type": "address",
- "name": "fromDelegate",
- "indexed": true
- },
- {
- "type": "address",
- "name": "toDelegate",
- "indexed": true
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "DelegateVotesChanged",
- "inputs": [
- {
- "type": "address",
- "name": "delegate",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "previousBalance",
- "indexed": false
- },
- {
- "type": "uint256",
- "name": "newBalance",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "GovernanceTransferred",
- "inputs": [
- {
- "type": "address",
- "name": "oldGovernance",
- "indexed": false
- },
- {
- "type": "address",
- "name": "newGovernance",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "MinimumStakeAmountSet",
- "inputs": [
- {
- "type": "uint96",
- "name": "amount",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "NotificationReceived",
- "inputs": [
- {
- "type": "uint96",
- "name": "amount",
- "indexed": false
- },
- {
- "type": "uint256",
- "name": "rewardMultipier",
- "indexed": false
- },
- {
- "type": "address",
- "name": "notifier",
- "indexed": false
- },
- {
- "type": "address[]",
- "name": "stakingProviders",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "NotificationRewardPushed",
- "inputs": [
- {
- "type": "uint96",
- "name": "reward",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "NotificationRewardSet",
- "inputs": [
- {
- "type": "uint96",
- "name": "reward",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "NotificationRewardWithdrawn",
- "inputs": [
- {
- "type": "address",
- "name": "recipient",
- "indexed": false
- },
- {
- "type": "uint96",
- "name": "amount",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "NotifierRewarded",
- "inputs": [
- {
- "type": "address",
- "name": "notifier",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "amount",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "PanicButtonSet",
- "inputs": [
- {
- "type": "address",
- "name": "application",
- "indexed": true
- },
- {
- "type": "address",
- "name": "panicButton",
- "indexed": true
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "SlashingProcessed",
- "inputs": [
- {
- "type": "address",
- "name": "caller",
- "indexed": true
- },
- {
- "type": "uint256",
- "name": "count",
- "indexed": false
- },
- {
- "type": "uint256",
- "name": "tAmount",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "Staked",
- "inputs": [
- {
- "type": "uint8",
- "name": "stakeType",
- "indexed": true
- },
- {
- "type": "address",
- "name": "owner",
- "indexed": true
- },
- {
- "type": "address",
- "name": "stakingProvider",
- "indexed": true
- },
- {
- "type": "address",
- "name": "beneficiary",
- "indexed": false
- },
- {
- "type": "address",
- "name": "authorizer",
- "indexed": false
- },
- {
- "type": "uint96",
- "name": "amount",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "TokensSeized",
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider",
- "indexed": true
- },
- {
- "type": "uint96",
- "name": "amount",
- "indexed": false
- },
- {
- "type": "bool",
- "name": "discrepancy",
- "indexed": true
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "ToppedUp",
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider",
- "indexed": true
- },
- {
- "type": "uint96",
- "name": "amount",
- "indexed": false
- }
- ]
- },
- {
- "type": "event",
- "anonymous": false,
- "name": "Unstaked",
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider",
- "indexed": true
- },
- {
- "type": "uint96",
- "name": "amount",
- "indexed": false
- }
- ]
- },
- {
- "type": "function",
- "name": "applicationInfo",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address"
- }
- ],
- "outputs": [
- {
- "type": "uint8",
- "name": "status"
- },
- {
- "type": "address",
- "name": "panicButton"
- }
- ]
- },
- {
- "type": "function",
- "name": "applications",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "uint256"
- }
- ],
- "outputs": [
- {
- "type": "address"
- }
- ]
- },
- {
- "type": "function",
- "name": "approveApplication",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "application"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "approveAuthorizationDecrease",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- }
- ],
- "outputs": [
- {
- "type": "uint96"
- }
- ]
- },
- {
- "type": "function",
- "name": "authorizationCeiling",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [],
- "outputs": [
- {
- "type": "uint256"
- }
- ]
- },
- {
- "type": "function",
- "name": "authorizedStake",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- },
- {
- "type": "address",
- "name": "application"
- }
- ],
- "outputs": [
- {
- "type": "uint96"
- }
- ]
- },
- {
- "type": "function",
- "name": "checkpoints",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "account"
- },
- {
- "type": "uint32",
- "name": "pos"
- }
- ],
- "outputs": [
- {
- "type": "tuple",
- "name": "checkpoint",
- "components": [
- {
- "type": "uint32",
- "name": "fromBlock"
- },
- {
- "type": "uint96",
- "name": "votes"
- }
- ]
- }
- ]
- },
- {
- "type": "function",
- "name": "delegateVoting",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- },
- {
- "type": "address",
- "name": "delegatee"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "delegates",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "account"
- }
- ],
- "outputs": [
- {
- "type": "address"
- }
- ]
- },
- {
- "type": "function",
- "name": "disableApplication",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "application"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "forceDecreaseAuthorization",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- },
- {
- "type": "address",
- "name": "application"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "getApplicationsLength",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [],
- "outputs": [
- {
- "type": "uint256"
- }
- ]
- },
- {
- "type": "function",
- "name": "getAvailableToAuthorize",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- },
- {
- "type": "address",
- "name": "application"
- }
- ],
- "outputs": [
- {
- "type": "uint96",
- "name": "availableTValue"
- }
- ]
- },
- {
- "type": "function",
- "name": "getMaxAuthorization",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- }
- ],
- "outputs": [
- {
- "type": "uint96"
- }
- ]
- },
- {
- "type": "function",
- "name": "getPastTotalSupply",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "uint256",
- "name": "blockNumber"
- }
- ],
- "outputs": [
- {
- "type": "uint96"
- }
- ]
- },
- {
- "type": "function",
- "name": "getPastVotes",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "account"
- },
- {
- "type": "uint256",
- "name": "blockNumber"
- }
- ],
- "outputs": [
- {
- "type": "uint96"
- }
- ]
- },
- {
- "type": "function",
- "name": "getStartStakingTimestamp",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- }
- ],
- "outputs": [
- {
- "type": "uint256"
- }
- ]
- },
- {
- "type": "function",
- "name": "getVotes",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "account"
- }
- ],
- "outputs": [
- {
- "type": "uint96"
- }
- ]
- },
- {
- "type": "function",
- "name": "governance",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [],
- "outputs": [
- {
- "type": "address"
- }
- ]
- },
- {
- "type": "function",
- "name": "increaseAuthorization",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- },
- {
- "type": "address",
- "name": "application"
- },
- {
- "type": "uint96",
- "name": "amount"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "initialize",
- "constant": false,
- "payable": false,
- "inputs": [],
- "outputs": []
- },
- {
- "type": "function",
- "name": "minTStakeAmount",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [],
- "outputs": [
- {
- "type": "uint96"
- }
- ]
- },
- {
- "type": "function",
- "name": "notifiersTreasury",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [],
- "outputs": [
- {
- "type": "uint256"
- }
- ]
- },
- {
- "type": "function",
- "name": "numCheckpoints",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "account"
- }
- ],
- "outputs": [
- {
- "type": "uint32"
- }
- ]
- },
- {
- "type": "function",
- "name": "pauseApplication",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "application"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "requestAuthorizationDecrease",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- },
- {
- "type": "address",
- "name": "application"
- },
- {
- "type": "uint96",
- "name": "amount"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "rolesOf",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- }
- ],
- "outputs": [
- {
- "type": "address",
- "name": "owner"
- },
- {
- "type": "address",
- "name": "beneficiary"
- },
- {
- "type": "address",
- "name": "authorizer"
- }
- ]
- },
- {
- "type": "function",
- "name": "seize",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "uint96",
- "name": "amount"
- },
- {
- "type": "uint256",
- "name": "rewardMultiplier"
- },
- {
- "type": "address",
- "name": "notifier"
- },
- {
- "type": "address[]",
- "name": "_stakingProviders"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "setAuthorizationCeiling",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "uint256",
- "name": "ceiling"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "setMinimumStakeAmount",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "uint96",
- "name": "amount"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "setPanicButton",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "application"
- },
- {
- "type": "address",
- "name": "panicButton"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "slash",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "uint96",
- "name": "amount"
- },
- {
- "type": "address[]",
- "name": "_stakingProviders"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "stakeAmount",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- }
- ],
- "outputs": [
- {
- "type": "uint96"
- }
- ]
- },
- {
- "type": "function",
- "name": "stakes",
- "constant": true,
- "stateMutability": "view",
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- }
- ],
- "outputs": [
- {
- "type": "uint96",
- "name": "tStake"
- },
- {
- "type": "uint96",
- "name": "keepInTStake"
- },
- {
- "type": "uint96",
- "name": "nuInTStake"
- }
- ]
- },
- {
- "type": "function",
- "name": "transferGovernance",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "newGuvnor"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "unstakeT",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "stakingProvider"
- },
- {
- "type": "uint96",
- "name": "amount"
- }
- ],
- "outputs": []
- },
- {
- "type": "function",
- "name": "withdrawNotificationReward",
- "constant": false,
- "payable": false,
- "inputs": [
- {
- "type": "address",
- "name": "recipient"
- },
- {
- "type": "uint96",
- "name": "amount"
- }
- ],
- "outputs": []
- }
- ]
-}
\ No newline at end of file
diff --git a/deploy/07_deploy_token_staking.ts b/deploy/07_deploy_token_staking.ts
index 0e7684be..8afeeb8e 100644
--- a/deploy/07_deploy_token_staking.ts
+++ b/deploy/07_deploy_token_staking.ts
@@ -1,5 +1,6 @@
import { HardhatRuntimeEnvironment } from "hardhat/types"
import { DeployFunction } from "hardhat-deploy/types"
+import * as fs from "fs"
import { ethers, upgrades } from "hardhat"
@@ -15,7 +16,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
// TODO: Consider upgradable deployment also for sepolia.
let tokenStakingAddress
- if (hre.network.name == "mainnet" || hre.network.name == "sepolia") {
+ if (hre.network.name === "mainnet" || hre.network.name === "sepolia") {
const TokenStaking = await ethers.getContractFactory("TokenStaking")
const tokenStaking = await upgrades.deployProxy(
@@ -29,34 +30,30 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
log(`Deployed TokenStaking with TransparentProxy at ${tokenStakingAddress}`)
const implementationInterface = tokenStaking.interface
- let jsonAbi = implementationInterface.format(ethers.utils.FormatTypes.json)
+ const jsonAbi = implementationInterface.format(ethers.utils.FormatTypes.json)
+
+ let parsedAbi: unknown[]
+ try {
+ parsedAbi = JSON.parse(jsonAbi as string) as unknown[]
+ } catch (e) {
+ throw new Error(`Failed to parse ABI from contract interface: ${e}`)
+ }
const tokenStakingDeployment = {
address: tokenStakingAddress,
- abi: JSON.parse(jsonAbi as string),
+ abi: parsedAbi,
}
- const fs = require("fs")
const deploymentsDir = `deployments/${hre.network.name}`
- fs.mkdirSync(deploymentsDir, { recursive: true })
+ await fs.promises.mkdir(deploymentsDir, { recursive: true })
await deployments.save("TokenStaking", tokenStakingDeployment)
- fs.writeFileSync(
- "TokenStaking.json",
- JSON.stringify(tokenStakingDeployment, null, 2),
- "utf8",
- function (err) {
- if (err) {
- console.log(err)
- }
- }
- )
- fs.writeFileSync(
+ await fs.promises.writeFile(
`${deploymentsDir}/TokenStaking.json`,
JSON.stringify(tokenStakingDeployment, null, 2),
"utf8"
)
- log(`Saved TokenStaking address and ABI in TokenStaking.json`)
+ log(`Saved TokenStaking address and ABI in ${deploymentsDir}/TokenStaking.json`)
} else {
const TokenStaking = await deployments.deploy("TokenStaking", {
from: deployer,
From b8bf5221fad61f608a1108cc684b9b8085d96621 Mon Sep 17 00:00:00 2001
From: Lev Akhnazarov
Date: Tue, 5 May 2026 17:41:47 +0100
Subject: [PATCH 9/9] fix(scripts): update fund-new-operator.sh and
setup-multiple-operators.sh to use positional arguments for cast wallet
address
- Refactored fund-new-operator.sh to utilize cast_send_ok for sending tokens, improving error handling.
- Modified setup-multiple-operators.sh to pass private keys as positional arguments to cast wallet address, addressing security concerns with environment variable exposure.
---
scripts/fund-new-operator.sh | 7 +++++--
scripts/setup-multiple-operators.sh | 8 +++++---
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/scripts/fund-new-operator.sh b/scripts/fund-new-operator.sh
index 155ba2d6..1e6a0916 100755
--- a/scripts/fund-new-operator.sh
+++ b/scripts/fund-new-operator.sh
@@ -41,9 +41,12 @@ fi
: "${NEW_OPERATOR_ADDRESS:?Run setup-new-staking-provider.js first}"
: "${CONTRACT_OWNER_ACCOUNT_PRIVATE_KEY:?Set CONTRACT_OWNER_ACCOUNT_PRIVATE_KEY (deployer with T balance)}"
+# shellcheck source=scripts/lib/cast-helpers.sh
+source "$SCRIPT_DIR/lib/cast-helpers.sh"
+
echo "=== Transfer 80,000 T to staking provider ==="
-ETH_PRIVATE_KEY="$CONTRACT_OWNER_ACCOUNT_PRIVATE_KEY" \
- cast send "$T_TOKEN" "transfer(address,uint256)" "$NEW_STAKING_PROVIDER_ADDRESS" "$AMOUNT_80K" \
+ETH_PRIVATE_KEY="$CONTRACT_OWNER_ACCOUNT_PRIVATE_KEY" cast_send_ok \
+ "$T_TOKEN" "transfer(address,uint256)" "$NEW_STAKING_PROVIDER_ADDRESS" "$AMOUNT_80K" \
--rpc-url "$CHAIN_API_URL"
echo ""
diff --git a/scripts/setup-multiple-operators.sh b/scripts/setup-multiple-operators.sh
index 3ddd5954..d46e65ee 100755
--- a/scripts/setup-multiple-operators.sh
+++ b/scripts/setup-multiple-operators.sh
@@ -167,7 +167,8 @@ resolve_t_minter_private_key() {
return 0
fi
if [ -n "${T_MINTER_PRIVATE_KEY:-}" ]; then
- _mk_addr=$(ETH_PRIVATE_KEY="${T_MINTER_PRIVATE_KEY}" cast wallet address)
+ # Foundry does not read ETH_PRIVATE_KEY for `cast wallet address`; pass key as positional arg.
+ _mk_addr=$(cast wallet address "${T_MINTER_PRIVATE_KEY}")
if [ "$(normalize_addr "$_mk_addr")" = "$_t_owner_lc" ]; then
printf '%s' "${T_MINTER_PRIVATE_KEY}"
return 0
@@ -282,7 +283,8 @@ fi
# Sourcing .env.operator-* must not clobber the deployer key (stale files sometimes set CONTRACT_OWNER_*).
_DEPLOYER_ACCOUNT_PRIVATE_KEY="$CONTRACT_OWNER_ACCOUNT_PRIVATE_KEY"
-_deployer_addr=$(ETH_PRIVATE_KEY="$_DEPLOYER_ACCOUNT_PRIVATE_KEY" cast wallet address)
+# Foundry does not read ETH_PRIVATE_KEY for `cast wallet address`; pass key as positional arg.
+_deployer_addr=$(cast wallet address "$_DEPLOYER_ACCOUNT_PRIVATE_KEY")
command -v python3 >/dev/null 2>&1 || {
echo "ERROR: python3 is required for --new (T balance checks and AUTO_FUND_T mint)." >&2
echo " Install python3 on the runner, then retry." >&2
@@ -323,7 +325,7 @@ for i in $(seq 1 "$N"); do
exit 1
fi
- _sp_derived=$(ETH_PRIVATE_KEY="$NEW_STAKING_PROVIDER_KEY" cast wallet address)
+ _sp_derived=$(cast wallet address "$NEW_STAKING_PROVIDER_KEY")
_sp_a=$(echo "$_sp_derived" | tr '[:upper:]' '[:lower:]')
_sp_b=$(echo "$NEW_STAKING_PROVIDER_ADDRESS" | tr '[:upper:]' '[:lower:]')
if [ "$_sp_a" != "$_sp_b" ]; then