diff --git a/flow.json b/flow.json index 15171781..0c54c0a4 100644 --- a/flow.json +++ b/flow.json @@ -102,6 +102,26 @@ "resourceID": "projects/flow-service-account-key/locations/global/keyRings/flow-service-account-signer-LL/cryptoKeys/flow-service-account-signer-LL/cryptoKeyVersions/1" } }, + "fungible_token": { + "address": "f233dcee88fe0abe", + "key": { + "type": "google-kms", + "index": 0, + "signatureAlgorithm": "ECDSA_P256", + "hashAlgorithm": "SHA2_256", + "resourceID": "projects/dl-flow/locations/global/keyRings/mainnet/cryptoKeys/service-account/cryptoKeyVersions/1" + } + }, + "staking_proxy": { + "address": "62430cf28c26d095", + "key": { + "type": "google-kms", + "index": 0, + "signatureAlgorithm": "ECDSA_P256", + "hashAlgorithm": "SHA2_256", + "resourceID": "projects/dl-flow/locations/global/keyRings/mainnet/cryptoKeys/token-admin/cryptoKeyVersions/1" + } + }, "emulator-account": { "address": "f8d6e0586b0a20c7", "key": "d5547bbeea9acdf1a95b0df2dbe2b3022acbcd850e83671594b6e240f01bacc9" diff --git a/transactions/update-contract/2026/apr-20-part-2/FungibleToken.cdc b/transactions/update-contract/2026/apr-20-part-2/FungibleToken.cdc new file mode 100644 index 00000000..f2717194 --- /dev/null +++ b/transactions/update-contract/2026/apr-20-part-2/FungibleToken.cdc @@ -0,0 +1,297 @@ +/** + +# The Flow Fungible Token standard + +## `FungibleToken` contract + +If a users wants to deploy a new token contract, their contract +needs to implement the FungibleToken interface and their tokens +need to implement the interfaces defined in this contract. + +/// Contributors (please add to this list if you contribute!): +/// - Joshua Hannan - https://github.com/joshuahannan +/// - Bastian Müller - https://twitter.com/turbolent +/// - Dete Shirley - https://twitter.com/dete73 +/// - Bjarte Karlsen - https://twitter.com/0xBjartek +/// - Austin Kline - https://twitter.com/austin_flowty +/// - Giovanni Sanchez - https://twitter.com/gio_incognito +/// - Deniz Edincik - https://twitter.com/bluesign +/// - Jonny - https://github.com/dryruner +/// +/// Repo reference: https://github.com/onflow/flow-ft + +## `Vault` resource interface + +Each fungible token resource type needs to implement the `Vault` resource interface. + +## `Provider`, `Receiver`, and `Balance` resource interfaces + +These interfaces declare pre-conditions and post-conditions that restrict +the execution of the functions in the Vault. + +It gives users the ability to make custom resources that implement +these interfaces to do various things with the tokens. +For example, a faucet can be implemented by conforming +to the Provider interface. + +*/ + +import ViewResolver from 0x1d7e57aa55817448 +import Burner from 0xf233dcee88fe0abe + +/// FungibleToken +/// +/// Fungible Token implementations should implement the fungible token +/// interface. +access(all) contract interface FungibleToken: ViewResolver { + + // An entitlement for allowing the withdrawal of tokens from a Vault + access(all) entitlement Withdraw + + /// The event that is emitted when tokens are withdrawn + /// from any Vault that implements the `Vault` interface + access(all) event Withdrawn(type: String, + amount: UFix64, + from: Address?, + fromUUID: UInt64, + withdrawnUUID: UInt64, + balanceAfter: UFix64) + + /// The event that is emitted when tokens are deposited to + /// any Vault that implements the `Vault` interface + access(all) event Deposited(type: String, + amount: UFix64, + to: Address?, + toUUID: UInt64, + depositedUUID: UInt64, + balanceAfter: UFix64) + + /// Event that is emitted when the global `Burner.burn()` method + /// is called with a non-zero balance + access(all) event Burned(type: String, amount: UFix64, fromUUID: UInt64) + + /// Balance + /// + /// The interface that provides a standard field + /// for representing balance + /// + access(all) resource interface Balance: Burner.Burnable { + access(all) var balance: UFix64 + + // This default implementation needs to be in a separate interface + // from the one in `Vault` so that the conditions get enforced + // in the correct one + access(contract) fun burnCallback() { + self.balance = 0.0 + } + } + + /// Provider + /// + /// The interface that enforces the requirements for withdrawing + /// tokens from the implementing type. + /// + /// It does not enforce requirements on `balance` here, + /// because it leaves open the possibility of creating custom providers + /// that do not necessarily need their own balance. + /// + access(all) resource interface Provider { + + /// Function to ask a provider if a specific amount of tokens + /// is available to be withdrawn + /// This could be useful to avoid panicking when calling withdraw + /// when the balance is unknown + /// Additionally, if the provider is pulling from multiple vaults + /// it only needs to check some of the vaults until the desired amount + /// is reached, potentially helping with performance. + /// + /// @param amount the amount of tokens requested to potentially withdraw + /// @return Bool Whether or not this amount is available to withdraw + /// + access(all) view fun isAvailableToWithdraw(amount: UFix64): Bool + + /// withdraw subtracts tokens from the implementing resource + /// and returns a Vault with the removed tokens. + /// + /// The function's access level is `access(Withdraw)` + /// So in order to access it, one would either need the object itself + /// or an entitled reference with `Withdraw`. + /// + /// @param amount the amount of tokens to withdraw from the resource + /// @return The Vault with the withdrawn tokens + /// + access(Withdraw) fun withdraw(amount: UFix64): @{Vault} { + post { + // `result` refers to the return value + result.balance == amount: + "FungibleToken.Provider.withdraw: Cannot withdraw tokens! The balance of the withdrawn tokens (\(result.balance)) is not equal to the amount requested to be withdrawn (\(amount))" + } + } + } + + /// Receiver + /// + /// The interface that enforces the requirements for depositing + /// tokens into the implementing type. + /// + /// We do not include a condition that checks the balance because + /// we want to give users the ability to make custom receivers that + /// can do custom things with the tokens, like split them up and + /// send them to different places. + /// + access(all) resource interface Receiver { + + /// deposit takes a Vault and deposits it into the implementing resource type + /// + /// @param from the Vault that contains the tokens to deposit + /// + access(all) fun deposit(from: @{Vault}) + + /// getSupportedVaultTypes returns a dictionary of Vault types + /// and whether the type is currently supported by this Receiver + /// + /// @return {Type: Bool} A dictionary that indicates the supported types + /// If a type is not supported, it should be `nil`, not false + /// + access(all) view fun getSupportedVaultTypes(): {Type: Bool} + + /// Returns whether or not the given type is accepted by the Receiver + /// A vault that can accept any type should just return true by default + /// + /// @param type The type to query about + /// @return Bool Whether or not the vault type is supported + /// + access(all) view fun isSupportedVaultType(type: Type): Bool + } + + /// Vault + /// Conforms to all other interfaces so that implementations + /// only have to conform to `Vault` + /// + access(all) resource interface Vault: Receiver, Provider, Balance, ViewResolver.Resolver, Burner.Burnable { + + /// Field that tracks the balance of a vault + access(all) var balance: UFix64 + + /// Called when a fungible token is burned via the `Burner.burn()` method + /// Implementations can do any bookkeeping or emit any events + /// that should be emitted when a vault is destroyed. + /// Many implementations will want to update the token's total supply + /// to reflect that the tokens have been burned and removed from the supply. + /// Implementations also need to set the balance to zero before the end of the function + /// This is to prevent vault owners from spamming fake Burned events. + access(contract) fun burnCallback() { + pre { + emit Burned( + type: self.getType().identifier, + amount: self.balance, + fromUUID: self.uuid + ) + } + post { + self.balance == 0.0: + "FungibleToken.Vault.burnCallback: Cannot burn this `Vault` with `Burner.burn()`. The balance must be set to zero during the `burnCallback` method so that it cannot be spammed." + } + } + + /// getSupportedVaultTypes + /// The default implementation is included here because vaults are expected + /// to only accepted their own type, so they have no need to provide an implementation + /// for this function + /// + access(all) view fun getSupportedVaultTypes(): {Type: Bool} { + // Below check is implemented to make sure that run-time type would + // only get returned when the parent resource conforms with `FungibleToken.Vault`. + if self.getType().isSubtype(of: Type<@{FungibleToken.Vault}>()) { + return {self.getType(): true} + } else { + // Return an empty dictionary as the default value for resource who don't + // implement `FungibleToken.Vault`, such as `FungibleTokenSwitchboard`, `TokenForwarder` etc. + return {} + } + } + + /// Checks if the given type is supported by this Vault + access(all) view fun isSupportedVaultType(type: Type): Bool { + return self.getSupportedVaultTypes()[type] ?? false + } + + /// withdraw subtracts `amount` from the Vault's balance + /// and returns a new Vault with the subtracted balance + /// + access(Withdraw) fun withdraw(amount: UFix64): @{Vault} { + pre { + self.balance >= amount: + "FungibleToken.Vault.withdraw: Cannot withdraw tokens! The amount requested to be withdrawn (\(amount)) is greater than the balance of the `Vault` (\(self.balance))." + } + post { + result.getType() == self.getType(): + "FungibleToken.Vault.withdraw: Cannot withdraw tokens! The withdraw method tried to return an incompatible `Vault` type <\(result.getType().identifier)>. It must return a `Vault` with the same type as self <\(self.getType().identifier)>." + + // use the special function `before` to get the value of the `balance` field + // at the beginning of the function execution + // + self.balance == before(self.balance) - amount: + "FungibleToken.Vault.withdraw: Cannot withdraw tokens! The sender's balance after the withdrawal (\(self.balance)) must be the difference of the previous balance (\(before(self.balance))) and the amount withdrawn (\(amount))" + + emit Withdrawn( + type: result.getType().identifier, + amount: amount, + from: self.owner?.address, + fromUUID: self.uuid, + withdrawnUUID: result.uuid, + balanceAfter: self.balance + ) + } + } + + /// deposit takes a Vault and adds its balance to the balance of this Vault + /// + access(all) fun deposit(from: @{FungibleToken.Vault}) { + // Assert that the concrete type of the deposited vault is the same + // as the vault that is accepting the deposit + pre { + from.isInstance(self.getType()): + "FungibleToken.Vault.deposit: Cannot deposit tokens! The type of the deposited tokens <\(from.getType().identifier)> has to be the same type as the `Vault` being deposited into <\(self.getType().identifier)>. Check that you are withdrawing and depositing to the correct paths in the sender and receiver accounts and that those paths hold the same `Vault` types." + } + post { + emit Deposited( + type: before(from.getType().identifier), + amount: before(from.balance), + to: self.owner?.address, + toUUID: self.uuid, + depositedUUID: before(from.uuid), + balanceAfter: self.balance + ) + self.balance == before(self.balance) + before(from.balance): + "FungibleToken.Vault.deposit: Cannot deposit tokens! The receiver's balance after the deposit (\(self.balance)) must be the sum of the previous balance (\(before(self.balance))) and the amount deposited (\(before(from.balance)))" + } + } + + /// createEmptyVault allows any user to create a new Vault that has a zero balance + /// + /// @return A Vault of the same type that has a balance of zero + access(all) fun createEmptyVault(): @{Vault} { + post { + result.balance == 0.0: + "FungibleToken.Vault.createEmptyVault: Empty `Vault` creation failed! The newly created `Vault` must have zero balance but it has a balance of \(result.balance)" + + result.getType() == self.getType(): + "FungibleToken.Vault.createEmptyVault: Empty `Vault` creation failed! The type of the new `Vault` <\(result.getType().identifier)> has to be the same type as the `Vault` that created it <\(self.getType().identifier)>." + } + } + } + + /// createEmptyVault allows any user to create a new Vault that has a zero balance + /// + /// @return A Vault of the requested type that has a balance of zero + access(all) fun createEmptyVault(vaultType: Type): @{FungibleToken.Vault} { + post { + result.balance == 0.0: + "FungibleToken.createEmptyVault: Empty `Vault` creation failed! The newly created `Vault` must have zero balance but it has a balance of \(result.balance)" + + result.getType() == vaultType: + "FungibleToken.createEmptyVault: Empty `Vault` creation failed! The type of the new `Vault` <\(result.getType().identifier)> has to be the same as the type that was requested <\(vaultType.identifier)>." + } + } +} \ No newline at end of file diff --git a/transactions/update-contract/2026/apr-20-part-2/README.md b/transactions/update-contract/2026/apr-20-part-2/README.md new file mode 100644 index 00000000..63a75872 --- /dev/null +++ b/transactions/update-contract/2026/apr-20-part-2/README.md @@ -0,0 +1,61 @@ +# FungibleToken and StakingProxy update + +Transactions to upgrade FungibleToken and StakingProxy contracts + +Signer: +1. Fungible Token: `0xf233dcee88fe0abe` +2. StakingProxy: `0x62430cf28c26d095` + +## Transactions + +[update contract](../../../../transactions/update-contract) + +### FungibleToken + +Used this to generate the contract code arguments: + +` wget https://raw.githubusercontent.com/onflow/flow-ft/refs/heads/master/contracts/FungibleToken.cdc` + +- Update imports + +`cat "./FungibleToken.cdc" | xxd -p | tr -d '\n'` + +Verified using: +``` +$ cat arguments-fungibletoken-contract.json | jq '.[1] | .value' | xxd -r -p > /tmp/temp.txt +$ diff /tmp/temp.txt FungibleToken.cdc +(Should produce no difference) +``` + +### StakingProxy + +Used this to generate the contract code arguments: + +` wget https://raw.githubusercontent.com/onflow/flow-core-contracts/refs/heads/master/contracts/StakingProxy.cdc` + +- Update imports + +`cat "./StakingProxy.cdc" | xxd -p | tr -d '\n'` + +Verified using: +``` +$ cat arguments-stakingproxy-contract.json | jq '.[1] | .value' | xxd -r -p > /tmp/temp.txt +$ diff /tmp/temp.txt StakingProxy.cdc +(Should produce no difference) +``` + + +## Steps to upgrade + +1. `flow transactions send ./templates/update_contract.cdc --signer fungible_token --args-json "$(cat "./transactions/update-contract/2026/apr-20-part-2/arguments-fungibletoken-contract.json")" -n mainnet --compute-limit 9999` +2. `flow transactions send ./templates/update_contract.cdc --signer staking_proxy --args-json "$(cat "./transactions/update-contract/2026/apr-20-part-2/arguments-stakingproxy-contract.json")" -n mainnet --compute-limit 9999` +___ + +### Results + +1. FungibleToken: + i. Success: https://www.flowscan.io/tx/26aec575a7aae0cc2676e2615ebe496642b25c4bb1e1548ad83a3da31ead24e2 +2. StakingProxy: + i. Failure: https://www.flowscan.io/tx/fcdb2001f42293f475be3465b8c5fa1ecc8d9890430ca2524b5678e1382350f4?tab=script - invalid signature + ii. Success: https://www.flowscan.io/tx/da7471dbe45ade9e737d65e55a057aaa821c0624533bac3d987f44e1b103cd1e + \ No newline at end of file diff --git a/transactions/update-contract/2026/apr-20-part-2/StakingProxy.cdc b/transactions/update-contract/2026/apr-20-part-2/StakingProxy.cdc new file mode 100644 index 00000000..30ee856d --- /dev/null +++ b/transactions/update-contract/2026/apr-20-part-2/StakingProxy.cdc @@ -0,0 +1,160 @@ +// This contract defines an interface for node stakers +// to use to be able to perform common staking actions + +// It also defines a resource that a node operator can +// use to store staking proxies for all of their node operation +// relationships + +access(all) contract StakingProxy { + + /// Entitlement that grants access to the node operator's privileged functions + access(all) entitlement NodeOperator + + /// path to store the node operator resource + /// in the node operators account for staking helper + access(all) let NodeOperatorCapabilityStoragePath: StoragePath + + access(all) let NodeOperatorCapabilityPublicPath: PublicPath + + /// Contains the node info associated with a node operator + access(all) struct NodeInfo { + + access(all) let id: String + access(all) let role: UInt8 + access(all) let networkingAddress: String + access(all) let networkingKey: String + access(all) let stakingKey: String + + init(nodeID: String, role: UInt8, networkingAddress: String, networkingKey: String, stakingKey: String) { + pre { + nodeID.length == 64: "StakingProxy.NodeInfo.init: Node ID length must be 32 bytes (64 hex characters) but got \(nodeID.length)" + networkingAddress.length > 0 && networkingKey.length > 0 && stakingKey.length > 0: + "StakingProxy.NodeInfo.init: Address and keys must all be non-empty" + } + self.id = nodeID + self.role = role + self.networkingAddress = networkingAddress + self.networkingKey = networkingKey + self.stakingKey = stakingKey + } + } + + /// The interface that limits what a node operator can access + /// from the staker who they operate for + access(all) struct interface NodeStakerProxy { + + access(all) fun stakeNewTokens(amount: UFix64) + + access(all) fun stakeUnstakedTokens(amount: UFix64) + + access(all) fun requestUnstaking(amount: UFix64) + + access(all) fun unstakeAll() + + access(all) fun withdrawUnstakedTokens(amount: UFix64) + + access(all) fun withdrawRewardedTokens(amount: UFix64) + + } + + /// The interface the describes what a delegator can do + access(all) struct interface NodeDelegatorProxy { + + access(all) fun delegateNewTokens(amount: UFix64) + + access(all) fun delegateUnstakedTokens(amount: UFix64) + + access(all) fun delegateRewardedTokens(amount: UFix64) + + access(all) fun requestUnstaking(amount: UFix64) + + access(all) fun withdrawUnstakedTokens(amount: UFix64) + + access(all) fun withdrawRewardedTokens(amount: UFix64) + } + + /// The interface that a node operator publishes their NodeStakerProxyHolder + /// as in order to allow other token holders to initialize + /// staking helper relationships with them + access(all) resource interface NodeStakerProxyHolderPublic { + + access(all) fun addStakingProxy(nodeID: String, proxy: {NodeStakerProxy}) + + access(all) fun getNodeInfo(nodeID: String): NodeInfo? + } + + /// The resource that node operators store in their accounts + /// to manage relationships with token holders who pay them off-chain + /// instead of with tokens + access(all) resource NodeStakerProxyHolder: NodeStakerProxyHolderPublic { + + /// Maps node IDs to any struct that implements the NodeStakerProxy interface + /// allows node operators to work with users with locked tokens + /// and with unstaked tokens + access(self) var stakingProxies: {String: {NodeStakerProxy}} + + /// Maps node IDs to NodeInfo + access(self) var nodeInfo: {String: NodeInfo} + + init() { + self.stakingProxies = {} + self.nodeInfo = {} + } + + /// Node operator calls this to add info about a node they + /// want to accept tokens for + access(NodeOperator) fun addNodeInfo(nodeInfo: NodeInfo) { + pre { + self.nodeInfo[nodeInfo.id] == nil + } + self.nodeInfo[nodeInfo.id] = nodeInfo + } + + /// Remove node info if it isn't in use any more + access(NodeOperator) fun removeNodeInfo(nodeID: String): NodeInfo { + return self.nodeInfo.remove(key: nodeID)! + } + + /// Published function to get all the info for a specific node ID + access(all) fun getNodeInfo(nodeID: String): NodeInfo? { + return self.nodeInfo[nodeID] + } + + /// Published function for a token holder who has signed up + /// the node operator's NodeInfo to operate a node + /// They store their `NodeStakerProxy` here to allow the node + /// operator to perform some staking actions also + access(all) fun addStakingProxy(nodeID: String, proxy: {NodeStakerProxy}) { + pre { + self.stakingProxies[nodeID] == nil + } + self.stakingProxies[nodeID] = proxy + } + + /// The node operator can call the removeStakingProxy function + /// to remove a staking proxy if it is no longer needed + access(NodeOperator) fun removeStakingProxy(nodeID: String): {NodeStakerProxy} { + pre { + self.stakingProxies[nodeID] != nil + } + + return self.stakingProxies.remove(key: nodeID)! + } + + /// Borrow a "reference" to the staking proxy so staking operations + /// can be performed with it + access(NodeOperator) fun borrowStakingProxy(nodeID: String): {NodeStakerProxy}? { + return self.stakingProxies[nodeID] + } + } + + /// Create a new proxy holder for a node operator + access(all) fun createProxyHolder(): @NodeStakerProxyHolder { + return <- create NodeStakerProxyHolder() + } + + init() { + self.NodeOperatorCapabilityStoragePath = /storage/nodeOperator + self.NodeOperatorCapabilityPublicPath = /public/nodeOperator + } +} diff --git a/transactions/update-contract/2026/apr-20-part-2/arguments-fungibletoken-contract.json b/transactions/update-contract/2026/apr-20-part-2/arguments-fungibletoken-contract.json new file mode 100644 index 00000000..78a612e8 --- /dev/null +++ b/transactions/update-contract/2026/apr-20-part-2/arguments-fungibletoken-contract.json @@ -0,0 +1,10 @@ +[ + { + "type": "String", + "value": "FungibleToken" + }, + { + "type": "String", + "value": "2f2a2a0a0a232054686520466c6f772046756e6769626c6520546f6b656e207374616e646172640a0a2323206046756e6769626c65546f6b656e6020636f6e74726163740a0a496620612075736572732077616e747320746f206465706c6f792061206e657720746f6b656e20636f6e74726163742c20746865697220636f6e74726163740a6e6565647320746f20696d706c656d656e74207468652046756e6769626c65546f6b656e20696e7465726661636520616e6420746865697220746f6b656e730a6e65656420746f20696d706c656d656e742074686520696e746572666163657320646566696e656420696e207468697320636f6e74726163742e0a0a2f2f2f20436f6e7472696275746f72732028706c656173652061646420746f2074686973206c69737420696620796f7520636f6e7472696275746521293a0a2f2f2f202d204a6f736875612048616e6e616e202d2068747470733a2f2f6769746875622e636f6d2f6a6f7368756168616e6e616e0a2f2f2f202d204261737469616e204dc3bc6c6c6572202d2068747470733a2f2f747769747465722e636f6d2f747572626f6c656e740a2f2f2f202d204465746520536869726c6579202d2068747470733a2f2f747769747465722e636f6d2f6465746537330a2f2f2f202d20426a61727465204b61726c73656e202d2068747470733a2f2f747769747465722e636f6d2f3078426a617274656b0a2f2f2f202d2041757374696e204b6c696e65202d2068747470733a2f2f747769747465722e636f6d2f61757374696e5f666c6f7774790a2f2f2f202d2047696f76616e6e692053616e6368657a202d2068747470733a2f2f747769747465722e636f6d2f67696f5f696e636f676e69746f0a2f2f2f202d2044656e697a204564696e63696b202d2068747470733a2f2f747769747465722e636f6d2f626c75657369676e0a2f2f2f202d204a6f6e6e79202d2068747470733a2f2f6769746875622e636f6d2f64727972756e65720a2f2f2f0a2f2f2f205265706f207265666572656e63653a2068747470733a2f2f6769746875622e636f6d2f6f6e666c6f772f666c6f772d66740a0a232320605661756c7460207265736f7572636520696e746572666163650a0a456163682066756e6769626c6520746f6b656e207265736f757263652074797065206e6565647320746f20696d706c656d656e742074686520605661756c7460207265736f7572636520696e746572666163652e0a0a2323206050726f7669646572602c20605265636569766572602c20616e64206042616c616e636560207265736f7572636520696e74657266616365730a0a546865736520696e7465726661636573206465636c617265207072652d636f6e646974696f6e7320616e6420706f73742d636f6e646974696f6e7320746861742072657374726963740a74686520657865637574696f6e206f66207468652066756e6374696f6e7320696e20746865205661756c742e0a0a497420676976657320757365727320746865206162696c69747920746f206d616b6520637573746f6d207265736f7572636573207468617420696d706c656d656e740a746865736520696e746572666163657320746f20646f20766172696f7573207468696e677320776974682074686520746f6b656e732e0a466f72206578616d706c652c2061206661756365742063616e20626520696d706c656d656e74656420627920636f6e666f726d696e670a746f207468652050726f766964657220696e746572666163652e0a0a2a2f0a0a696d706f727420566965775265736f6c7665722066726f6d203078316437653537616135353831373434380a696d706f7274204275726e65722066726f6d203078663233336463656538386665306162650a0a2f2f2f2046756e6769626c65546f6b656e0a2f2f2f0a2f2f2f2046756e6769626c6520546f6b656e20696d706c656d656e746174696f6e732073686f756c6420696d706c656d656e74207468652066756e6769626c6520746f6b656e0a2f2f2f20696e746572666163652e0a61636365737328616c6c2920636f6e747261637420696e746572666163652046756e6769626c65546f6b656e3a20566965775265736f6c766572207b0a0a202020202f2f20416e20656e7469746c656d656e7420666f7220616c6c6f77696e6720746865207769746864726177616c206f6620746f6b656e732066726f6d2061205661756c740a2020202061636365737328616c6c2920656e7469746c656d656e742057697468647261770a0a202020202f2f2f20546865206576656e74207468617420697320656d6974746564207768656e20746f6b656e73206172652077697468647261776e0a202020202f2f2f2066726f6d20616e79205661756c74207468617420696d706c656d656e74732074686520605661756c746020696e746572666163650a2020202061636365737328616c6c29206576656e742057697468647261776e28747970653a20537472696e672c0a2020202020202020202020202020202020202020202020202020202020202020616d6f756e743a205546697836342c0a202020202020202020202020202020202020202020202020202020202020202066726f6d3a20416464726573733f2c0a202020202020202020202020202020202020202020202020202020202020202066726f6d555549443a2055496e7436342c0a202020202020202020202020202020202020202020202020202020202020202077697468647261776e555549443a2055496e7436342c0a202020202020202020202020202020202020202020202020202020202020202062616c616e636541667465723a20554669783634290a0a202020202f2f2f20546865206576656e74207468617420697320656d6974746564207768656e20746f6b656e7320617265206465706f736974656420746f0a202020202f2f2f20616e79205661756c74207468617420696d706c656d656e74732074686520605661756c746020696e746572666163650a2020202061636365737328616c6c29206576656e74204465706f736974656428747970653a20537472696e672c0a2020202020202020202020202020202020202020202020202020202020202020616d6f756e743a205546697836342c0a2020202020202020202020202020202020202020202020202020202020202020746f3a20416464726573733f2c0a2020202020202020202020202020202020202020202020202020202020202020746f555549443a2055496e7436342c0a20202020202020202020202020202020202020202020202020202020202020206465706f7369746564555549443a2055496e7436342c0a202020202020202020202020202020202020202020202020202020202020202062616c616e636541667465723a20554669783634290a0a202020202f2f2f204576656e74207468617420697320656d6974746564207768656e2074686520676c6f62616c20604275726e65722e6275726e282960206d6574686f640a202020202f2f2f2069732063616c6c656420776974682061206e6f6e2d7a65726f2062616c616e63650a2020202061636365737328616c6c29206576656e74204275726e656428747970653a20537472696e672c20616d6f756e743a205546697836342c2066726f6d555549443a2055496e743634290a0a202020202f2f2f2042616c616e63650a202020202f2f2f0a202020202f2f2f2054686520696e7465726661636520746861742070726f76696465732061207374616e64617264206669656c640a202020202f2f2f20666f7220726570726573656e74696e672062616c616e63650a202020202f2f2f0a2020202061636365737328616c6c29207265736f7572636520696e746572666163652042616c616e63653a204275726e65722e4275726e61626c65207b0a202020202020202061636365737328616c6c29207661722062616c616e63653a205546697836340a0a20202020202020202f2f20546869732064656661756c7420696d706c656d656e746174696f6e206e6565647320746f20626520696e206120736570617261746520696e746572666163650a20202020202020202f2f2066726f6d20746865206f6e6520696e20605661756c746020736f20746861742074686520636f6e646974696f6e732067657420656e666f726365640a20202020202020202f2f20696e2074686520636f7272656374206f6e650a202020202020202061636365737328636f6e7472616374292066756e206275726e43616c6c6261636b2829207b0a20202020202020202020202073656c662e62616c616e6365203d20302e300a20202020202020207d0a202020207d0a0a202020202f2f2f2050726f76696465720a202020202f2f2f0a202020202f2f2f2054686520696e74657266616365207468617420656e666f726365732074686520726571756972656d656e747320666f72207769746864726177696e670a202020202f2f2f20746f6b656e732066726f6d2074686520696d706c656d656e74696e6720747970652e0a202020202f2f2f0a202020202f2f2f20497420646f6573206e6f7420656e666f72636520726571756972656d656e7473206f6e206062616c616e63656020686572652c0a202020202f2f2f2062656361757365206974206c6561766573206f70656e2074686520706f73736962696c697479206f66206372656174696e6720637573746f6d2070726f7669646572730a202020202f2f2f207468617420646f206e6f74206e65636573736172696c79206e656564207468656972206f776e2062616c616e63652e0a202020202f2f2f0a2020202061636365737328616c6c29207265736f7572636520696e746572666163652050726f7669646572207b0a0a20202020202020202f2f2f2046756e6374696f6e20746f2061736b20612070726f7669646572206966206120737065636966696320616d6f756e74206f6620746f6b656e730a20202020202020202f2f2f20697320617661696c61626c6520746f2062652077697468647261776e0a20202020202020202f2f2f205468697320636f756c642062652075736566756c20746f2061766f69642070616e69636b696e67207768656e2063616c6c696e672077697468647261770a20202020202020202f2f2f207768656e207468652062616c616e636520697320756e6b6e6f776e0a20202020202020202f2f2f204164646974696f6e616c6c792c206966207468652070726f76696465722069732070756c6c696e672066726f6d206d756c7469706c65207661756c74730a20202020202020202f2f2f206974206f6e6c79206e6565647320746f20636865636b20736f6d65206f6620746865207661756c747320756e74696c20746865206465736972656420616d6f756e740a20202020202020202f2f2f20697320726561636865642c20706f74656e7469616c6c792068656c70696e67207769746820706572666f726d616e63652e0a20202020202020202f2f2f0a20202020202020202f2f2f2040706172616d20616d6f756e742074686520616d6f756e74206f6620746f6b656e732072657175657374656420746f20706f74656e7469616c6c792077697468647261770a20202020202020202f2f2f204072657475726e20426f6f6c2057686574686572206f72206e6f74207468697320616d6f756e7420697320617661696c61626c6520746f2077697468647261770a20202020202020202f2f2f200a202020202020202061636365737328616c6c2920766965772066756e206973417661696c61626c65546f576974686472617728616d6f756e743a20554669783634293a20426f6f6c0a0a20202020202020202f2f2f2077697468647261772073756274726163747320746f6b656e732066726f6d2074686520696d706c656d656e74696e67207265736f757263650a20202020202020202f2f2f20616e642072657475726e732061205661756c742077697468207468652072656d6f76656420746f6b656e732e0a20202020202020202f2f2f0a20202020202020202f2f2f205468652066756e6374696f6e277320616363657373206c6576656c206973206061636365737328576974686472617729600a20202020202020202f2f2f20536f20696e206f7264657220746f206163636573732069742c206f6e6520776f756c6420656974686572206e65656420746865206f626a65637420697473656c660a20202020202020202f2f2f206f7220616e20656e7469746c6564207265666572656e6365207769746820605769746864726177602e0a20202020202020202f2f2f0a20202020202020202f2f2f2040706172616d20616d6f756e742074686520616d6f756e74206f6620746f6b656e7320746f2077697468647261772066726f6d20746865207265736f757263650a20202020202020202f2f2f204072657475726e20546865205661756c742077697468207468652077697468647261776e20746f6b656e730a20202020202020202f2f2f0a2020202020202020616363657373285769746864726177292066756e20776974686472617728616d6f756e743a20554669783634293a20407b5661756c747d207b0a202020202020202020202020706f7374207b0a202020202020202020202020202020202f2f2060726573756c74602072656665727320746f207468652072657475726e2076616c75650a20202020202020202020202020202020726573756c742e62616c616e6365203d3d20616d6f756e743a0a20202020202020202020202020202020202020202246756e6769626c65546f6b656e2e50726f76696465722e77697468647261773a2043616e6e6f7420776974686472617720746f6b656e7321205468652062616c616e6365206f66207468652077697468647261776e20746f6b656e7320285c28726573756c742e62616c616e63652929206973206e6f7420657175616c20746f2074686520616d6f756e742072657175657374656420746f2062652077697468647261776e20285c28616d6f756e742929220a2020202020202020202020207d0a20202020202020207d0a202020207d0a0a202020202f2f2f2052656365697665720a202020202f2f2f0a202020202f2f2f2054686520696e74657266616365207468617420656e666f726365732074686520726571756972656d656e747320666f72206465706f736974696e670a202020202f2f2f20746f6b656e7320696e746f2074686520696d706c656d656e74696e6720747970652e0a202020202f2f2f0a202020202f2f2f20576520646f206e6f7420696e636c756465206120636f6e646974696f6e207468617420636865636b73207468652062616c616e636520626563617573650a202020202f2f2f2077652077616e7420746f206769766520757365727320746865206162696c69747920746f206d616b6520637573746f6d2072656365697665727320746861740a202020202f2f2f2063616e20646f20637573746f6d207468696e677320776974682074686520746f6b656e732c206c696b652073706c6974207468656d20757020616e640a202020202f2f2f2073656e64207468656d20746f20646966666572656e7420706c616365732e0a202020202f2f2f0a2020202061636365737328616c6c29207265736f7572636520696e74657266616365205265636569766572207b0a0a20202020202020202f2f2f206465706f7369742074616b65732061205661756c7420616e64206465706f7369747320697420696e746f2074686520696d706c656d656e74696e67207265736f7572636520747970650a20202020202020202f2f2f0a20202020202020202f2f2f2040706172616d2066726f6d20746865205661756c74207468617420636f6e7461696e732074686520746f6b656e7320746f206465706f7369740a20202020202020202f2f2f0a202020202020202061636365737328616c6c292066756e206465706f7369742866726f6d3a20407b5661756c747d290a0a20202020202020202f2f2f20676574537570706f727465645661756c7454797065732072657475726e7320612064696374696f6e617279206f66205661756c742074797065730a20202020202020202f2f2f20616e6420776865746865722074686520747970652069732063757272656e746c7920737570706f7274656420627920746869732052656365697665720a20202020202020202f2f2f0a20202020202020202f2f2f204072657475726e207b547970653a20426f6f6c7d20412064696374696f6e617279207468617420696e646963617465732074686520737570706f727465642074797065730a20202020202020202f2f2f20202020202020202020202020202020202020202020496620612074797065206973206e6f7420737570706f727465642c2069742073686f756c6420626520606e696c602c206e6f742066616c73650a20202020202020202f2f2f0a202020202020202061636365737328616c6c2920766965772066756e20676574537570706f727465645661756c74547970657328293a207b547970653a20426f6f6c7d0a0a20202020202020202f2f2f2052657475726e732077686574686572206f72206e6f742074686520676976656e2074797065206973206163636570746564206279207468652052656365697665720a20202020202020202f2f2f2041207661756c7420746861742063616e2061636365707420616e7920747970652073686f756c64206a7573742072657475726e20747275652062792064656661756c740a20202020202020202f2f2f0a20202020202020202f2f2f2040706172616d207479706520546865207479706520746f2071756572792061626f75740a20202020202020202f2f2f204072657475726e20426f6f6c2057686574686572206f72206e6f7420746865207661756c74207479706520697320737570706f727465640a20202020202020202f2f2f0a202020202020202061636365737328616c6c2920766965772066756e206973537570706f727465645661756c745479706528747970653a2054797065293a20426f6f6c0a202020207d0a0a202020202f2f2f205661756c740a202020202f2f2f20436f6e666f726d7320746f20616c6c206f7468657220696e746572666163657320736f207468617420696d706c656d656e746174696f6e730a202020202f2f2f206f6e6c79206861766520746f20636f6e666f726d20746f20605661756c74600a202020202f2f2f0a2020202061636365737328616c6c29207265736f7572636520696e74657266616365205661756c743a2052656365697665722c2050726f76696465722c2042616c616e63652c20566965775265736f6c7665722e5265736f6c7665722c204275726e65722e4275726e61626c65207b0a0a20202020202020202f2f2f204669656c64207468617420747261636b73207468652062616c616e6365206f662061207661756c740a202020202020202061636365737328616c6c29207661722062616c616e63653a205546697836340a0a20202020202020202f2f2f2043616c6c6564207768656e20612066756e6769626c6520746f6b656e206973206275726e6564207669612074686520604275726e65722e6275726e282960206d6574686f640a20202020202020202f2f2f20496d706c656d656e746174696f6e732063616e20646f20616e7920626f6f6b6b656570696e67206f7220656d697420616e79206576656e74730a20202020202020202f2f2f20746861742073686f756c6420626520656d6974746564207768656e2061207661756c742069732064657374726f7965642e0a20202020202020202f2f2f204d616e7920696d706c656d656e746174696f6e732077696c6c2077616e7420746f207570646174652074686520746f6b656e277320746f74616c20737570706c790a20202020202020202f2f2f20746f207265666c65637420746861742074686520746f6b656e732068617665206265656e206275726e656420616e642072656d6f7665642066726f6d2074686520737570706c792e0a20202020202020202f2f2f20496d706c656d656e746174696f6e7320616c736f206e65656420746f20736574207468652062616c616e636520746f207a65726f206265666f72652074686520656e64206f66207468652066756e6374696f6e0a20202020202020202f2f2f205468697320697320746f2070726576656e74207661756c74206f776e6572732066726f6d207370616d6d696e672066616b65204275726e6564206576656e74732e0a202020202020202061636365737328636f6e7472616374292066756e206275726e43616c6c6261636b2829207b0a202020202020202020202020707265207b0a20202020202020202020202020202020656d6974204275726e6564280a2020202020202020202020202020202020202020747970653a2073656c662e6765745479706528292e6964656e7469666965722c0a2020202020202020202020202020202020202020616d6f756e743a2073656c662e62616c616e63652c0a202020202020202020202020202020202020202066726f6d555549443a2073656c662e757569640a20202020202020202020202020202020290a2020202020202020202020207d0a202020202020202020202020706f7374207b0a2020202020202020202020202020202073656c662e62616c616e6365203d3d20302e303a0a20202020202020202020202020202020202020202246756e6769626c65546f6b656e2e5661756c742e6275726e43616c6c6261636b3a2043616e6e6f74206275726e207468697320605661756c7460207769746820604275726e65722e6275726e2829602e205468652062616c616e6365206d7573742062652073657420746f207a65726f20647572696e672074686520606275726e43616c6c6261636b60206d6574686f6420736f20746861742069742063616e6e6f74206265207370616d6d65642e220a2020202020202020202020207d0a20202020202020207d0a0a20202020202020202f2f2f20676574537570706f727465645661756c7454797065730a20202020202020202f2f2f205468652064656661756c7420696d706c656d656e746174696f6e20697320696e636c7564656420686572652062656361757365207661756c7473206172652065787065637465640a20202020202020202f2f2f20746f206f6e6c79206163636570746564207468656972206f776e20747970652c20736f20746865792068617665206e6f206e65656420746f2070726f7669646520616e20696d706c656d656e746174696f6e0a20202020202020202f2f2f20666f7220746869732066756e6374696f6e0a20202020202020202f2f2f0a202020202020202061636365737328616c6c2920766965772066756e20676574537570706f727465645661756c74547970657328293a207b547970653a20426f6f6c7d207b0a2020202020202020202020202f2f2042656c6f7720636865636b20697320696d706c656d656e74656420746f206d616b65207375726520746861742072756e2d74696d65207479706520776f756c640a2020202020202020202020202f2f206f6e6c79206765742072657475726e6564207768656e2074686520706172656e74207265736f7572636520636f6e666f726d732077697468206046756e6769626c65546f6b656e2e5661756c74602e200a20202020202020202020202069662073656c662e6765745479706528292e697353756274797065286f663a20547970653c407b46756e6769626c65546f6b656e2e5661756c747d3e282929207b0a2020202020202020202020202020202072657475726e207b73656c662e6765745479706528293a20747275657d0a2020202020202020202020207d20656c7365207b0a202020202020202020202020202020202f2f2052657475726e20616e20656d7074792064696374696f6e617279206173207468652064656661756c742076616c756520666f72207265736f757263652077686f20646f6e27740a202020202020202020202020202020202f2f20696d706c656d656e74206046756e6769626c65546f6b656e2e5661756c74602c2073756368206173206046756e6769626c65546f6b656e537769746368626f617264602c2060546f6b656e466f7277617264657260206574632e0a2020202020202020202020202020202072657475726e207b7d0a2020202020202020202020207d0a20202020202020207d0a0a20202020202020202f2f2f20436865636b732069662074686520676976656e207479706520697320737570706f727465642062792074686973205661756c740a202020202020202061636365737328616c6c2920766965772066756e206973537570706f727465645661756c745479706528747970653a2054797065293a20426f6f6c207b0a20202020202020202020202072657475726e2073656c662e676574537570706f727465645661756c74547970657328295b747970655d203f3f2066616c73650a20202020202020207d0a0a20202020202020202f2f2f207769746864726177207375627472616374732060616d6f756e74602066726f6d20746865205661756c7427732062616c616e63650a20202020202020202f2f2f20616e642072657475726e732061206e6577205661756c7420776974682074686520737562747261637465642062616c616e63650a20202020202020202f2f2f0a2020202020202020616363657373285769746864726177292066756e20776974686472617728616d6f756e743a20554669783634293a20407b5661756c747d207b0a202020202020202020202020707265207b0a2020202020202020202020202020202073656c662e62616c616e6365203e3d20616d6f756e743a0a20202020202020202020202020202020202020202246756e6769626c65546f6b656e2e5661756c742e77697468647261773a2043616e6e6f7420776974686472617720746f6b656e73212054686520616d6f756e742072657175657374656420746f2062652077697468647261776e20285c28616d6f756e7429292069732067726561746572207468616e207468652062616c616e6365206f662074686520605661756c746020285c2873656c662e62616c616e636529292e220a2020202020202020202020207d0a202020202020202020202020706f7374207b0a20202020202020202020202020202020726573756c742e676574547970652829203d3d2073656c662e6765745479706528293a0a20202020202020202020202020202020202020202246756e6769626c65546f6b656e2e5661756c742e77697468647261773a2043616e6e6f7420776974686472617720746f6b656e732120546865207769746864726177206d6574686f6420747269656420746f2072657475726e20616e20696e636f6d70617469626c6520605661756c74602074797065203c5c28726573756c742e6765745479706528292e6964656e746966696572293e2e204974206d7573742072657475726e206120605661756c74602077697468207468652073616d6520747970652061732073656c66203c5c2873656c662e6765745479706528292e6964656e746966696572293e2e220a0a202020202020202020202020202020202f2f2075736520746865207370656369616c2066756e6374696f6e20606265666f72656020746f20676574207468652076616c7565206f6620746865206062616c616e636560206669656c640a202020202020202020202020202020202f2f2061742074686520626567696e6e696e67206f66207468652066756e6374696f6e20657865637574696f6e0a202020202020202020202020202020202f2f0a2020202020202020202020202020202073656c662e62616c616e6365203d3d206265666f72652873656c662e62616c616e636529202d20616d6f756e743a0a20202020202020202020202020202020202020202246756e6769626c65546f6b656e2e5661756c742e77697468647261773a2043616e6e6f7420776974686472617720746f6b656e7321205468652073656e64657227732062616c616e636520616674657220746865207769746864726177616c20285c2873656c662e62616c616e63652929206d7573742062652074686520646966666572656e6365206f66207468652070726576696f75732062616c616e636520285c286265666f72652873656c662e62616c616e636529292920616e642074686520616d6f756e742077697468647261776e20285c28616d6f756e742929220a0a20202020202020202020202020202020656d69742057697468647261776e280a202020202020202020202020202020202020202020202020747970653a20726573756c742e6765745479706528292e6964656e7469666965722c0a202020202020202020202020202020202020202020202020616d6f756e743a20616d6f756e742c0a20202020202020202020202020202020202020202020202066726f6d3a2073656c662e6f776e65723f2e616464726573732c0a20202020202020202020202020202020202020202020202066726f6d555549443a2073656c662e757569642c0a20202020202020202020202020202020202020202020202077697468647261776e555549443a20726573756c742e757569642c0a20202020202020202020202020202020202020202020202062616c616e636541667465723a2073656c662e62616c616e63650a20202020202020202020202020202020290a2020202020202020202020207d0a20202020202020207d0a0a20202020202020202f2f2f206465706f7369742074616b65732061205661756c7420616e642061646473206974732062616c616e636520746f207468652062616c616e6365206f662074686973205661756c740a20202020202020202f2f2f0a202020202020202061636365737328616c6c292066756e206465706f7369742866726f6d3a20407b46756e6769626c65546f6b656e2e5661756c747d29207b0a2020202020202020202020202f2f2041737365727420746861742074686520636f6e63726574652074797065206f6620746865206465706f7369746564207661756c74206973207468652073616d650a2020202020202020202020202f2f20617320746865207661756c74207468617420697320616363657074696e6720746865206465706f7369740a202020202020202020202020707265207b0a2020202020202020202020202020202066726f6d2e6973496e7374616e63652873656c662e676574547970652829293a0a20202020202020202020202020202020202020202246756e6769626c65546f6b656e2e5661756c742e6465706f7369743a2043616e6e6f74206465706f73697420746f6b656e7321205468652074797065206f6620746865206465706f736974656420746f6b656e73203c5c2866726f6d2e6765745479706528292e6964656e746966696572293e2068617320746f206265207468652073616d6520747970652061732074686520605661756c7460206265696e67206465706f736974656420696e746f203c5c2873656c662e6765745479706528292e6964656e746966696572293e2e20436865636b207468617420796f7520617265207769746864726177696e6720616e64206465706f736974696e6720746f2074686520636f727265637420706174687320696e207468652073656e64657220616e64207265636569766572206163636f756e747320616e6420746861742074686f736520706174687320686f6c64207468652073616d6520605661756c74602074797065732e220a2020202020202020202020207d0a202020202020202020202020706f7374207b0a20202020202020202020202020202020656d6974204465706f7369746564280a202020202020202020202020202020202020202020202020747970653a206265666f72652866726f6d2e6765745479706528292e6964656e746966696572292c0a202020202020202020202020202020202020202020202020616d6f756e743a206265666f72652866726f6d2e62616c616e6365292c0a202020202020202020202020202020202020202020202020746f3a2073656c662e6f776e65723f2e616464726573732c0a202020202020202020202020202020202020202020202020746f555549443a2073656c662e757569642c0a2020202020202020202020202020202020202020202020206465706f7369746564555549443a206265666f72652866726f6d2e75756964292c0a20202020202020202020202020202020202020202020202062616c616e636541667465723a2073656c662e62616c616e63650a20202020202020202020202020202020290a2020202020202020202020202020202073656c662e62616c616e6365203d3d206265666f72652873656c662e62616c616e636529202b206265666f72652866726f6d2e62616c616e6365293a0a20202020202020202020202020202020202020202246756e6769626c65546f6b656e2e5661756c742e6465706f7369743a2043616e6e6f74206465706f73697420746f6b656e73212054686520726563656976657227732062616c616e636520616674657220746865206465706f73697420285c2873656c662e62616c616e63652929206d757374206265207468652073756d206f66207468652070726576696f75732062616c616e636520285c286265666f72652873656c662e62616c616e636529292920616e642074686520616d6f756e74206465706f736974656420285c286265666f72652866726f6d2e62616c616e6365292929220a2020202020202020202020207d0a20202020202020207d0a0a20202020202020202f2f2f20637265617465456d7074795661756c7420616c6c6f777320616e79207573657220746f206372656174652061206e6577205661756c742074686174206861732061207a65726f2062616c616e63650a20202020202020202f2f2f0a20202020202020202f2f2f204072657475726e2041205661756c74206f66207468652073616d65207479706520746861742068617320612062616c616e6365206f66207a65726f0a202020202020202061636365737328616c6c292066756e20637265617465456d7074795661756c7428293a20407b5661756c747d207b0a202020202020202020202020706f7374207b0a20202020202020202020202020202020726573756c742e62616c616e6365203d3d20302e303a0a20202020202020202020202020202020202020202246756e6769626c65546f6b656e2e5661756c742e637265617465456d7074795661756c743a20456d70747920605661756c7460206372656174696f6e206661696c65642120546865206e65776c79206372656174656420605661756c7460206d7573742068617665207a65726f2062616c616e6365206275742069742068617320612062616c616e6365206f66205c28726573756c742e62616c616e636529220a0a20202020202020202020202020202020726573756c742e676574547970652829203d3d2073656c662e6765745479706528293a0a20202020202020202020202020202020202020202246756e6769626c65546f6b656e2e5661756c742e637265617465456d7074795661756c743a20456d70747920605661756c7460206372656174696f6e206661696c656421205468652074797065206f6620746865206e657720605661756c7460203c5c28726573756c742e6765745479706528292e6964656e746966696572293e2068617320746f206265207468652073616d6520747970652061732074686520605661756c746020746861742063726561746564206974203c5c2873656c662e6765745479706528292e6964656e746966696572293e2e220a2020202020202020202020207d0a20202020202020207d0a202020207d0a0a202020202f2f2f20637265617465456d7074795661756c7420616c6c6f777320616e79207573657220746f206372656174652061206e6577205661756c742074686174206861732061207a65726f2062616c616e63650a202020202f2f2f0a202020202f2f2f204072657475726e2041205661756c74206f662074686520726571756573746564207479706520746861742068617320612062616c616e6365206f66207a65726f0a2020202061636365737328616c6c292066756e20637265617465456d7074795661756c74287661756c74547970653a2054797065293a20407b46756e6769626c65546f6b656e2e5661756c747d207b0a2020202020202020706f7374207b0a202020202020202020202020726573756c742e62616c616e6365203d3d20302e303a0a202020202020202020202020202020202246756e6769626c65546f6b656e2e637265617465456d7074795661756c743a20456d70747920605661756c7460206372656174696f6e206661696c65642120546865206e65776c79206372656174656420605661756c7460206d7573742068617665207a65726f2062616c616e6365206275742069742068617320612062616c616e6365206f66205c28726573756c742e62616c616e636529220a0a202020202020202020202020726573756c742e676574547970652829203d3d207661756c74547970653a0a202020202020202020202020202020202246756e6769626c65546f6b656e2e637265617465456d7074795661756c743a20456d70747920605661756c7460206372656174696f6e206661696c656421205468652074797065206f6620746865206e657720605661756c7460203c5c28726573756c742e6765745479706528292e6964656e746966696572293e2068617320746f206265207468652073616d6520617320746865207479706520746861742077617320726571756573746564203c5c287661756c74547970652e6964656e746966696572293e2e220a20202020202020207d0a202020207d0a7d" + } +] diff --git a/transactions/update-contract/2026/apr-20-part-2/arguments-stakingproxy-contract.json b/transactions/update-contract/2026/apr-20-part-2/arguments-stakingproxy-contract.json new file mode 100644 index 00000000..171a6639 --- /dev/null +++ b/transactions/update-contract/2026/apr-20-part-2/arguments-stakingproxy-contract.json @@ -0,0 +1,10 @@ +[ + { + "type": "String", + "value": "StakingProxy" + }, + { + "type": "String", + "value": "2f2f205468697320636f6e747261637420646566696e657320616e20696e7465726661636520666f72206e6f6465207374616b6572730a2f2f20746f2075736520746f2062652061626c6520746f20706572666f726d20636f6d6d6f6e207374616b696e6720616374696f6e730a0a2f2f20497420616c736f20646566696e65732061207265736f7572636520746861742061206e6f6465206f70657261746f722063616e0a2f2f2075736520746f2073746f7265207374616b696e672070726f7869657320666f7220616c6c206f66207468656972206e6f6465206f7065726174696f6e0a2f2f2072656c6174696f6e73686970730a0a61636365737328616c6c2920636f6e7472616374205374616b696e6750726f7879207b0a0a202020202f2f2f20456e7469746c656d656e742074686174206772616e74732061636365737320746f20746865206e6f6465206f70657261746f7227732070726976696c656765642066756e6374696f6e730a2020202061636365737328616c6c2920656e7469746c656d656e74204e6f64654f70657261746f720a0a202020202f2f2f207061746820746f2073746f726520746865206e6f6465206f70657261746f72207265736f757263650a202020202f2f2f20696e20746865206e6f6465206f70657261746f7273206163636f756e7420666f72207374616b696e672068656c7065720a2020202061636365737328616c6c29206c6574204e6f64654f70657261746f724361706162696c69747953746f72616765506174683a2053746f72616765506174680a0a2020202061636365737328616c6c29206c6574204e6f64654f70657261746f724361706162696c6974795075626c6963506174683a205075626c6963506174680a0a202020202f2f2f20436f6e7461696e7320746865206e6f646520696e666f206173736f63696174656420776974682061206e6f6465206f70657261746f720a2020202061636365737328616c6c2920737472756374204e6f6465496e666f207b0a0a202020202020202061636365737328616c6c29206c65742069643a20537472696e670a202020202020202061636365737328616c6c29206c657420726f6c653a2055496e74380a202020202020202061636365737328616c6c29206c6574206e6574776f726b696e67416464726573733a20537472696e670a202020202020202061636365737328616c6c29206c6574206e6574776f726b696e674b65793a20537472696e670a202020202020202061636365737328616c6c29206c6574207374616b696e674b65793a20537472696e670a0a2020202020202020696e6974286e6f646549443a20537472696e672c20726f6c653a2055496e74382c206e6574776f726b696e67416464726573733a20537472696e672c206e6574776f726b696e674b65793a20537472696e672c207374616b696e674b65793a20537472696e6729207b0a202020202020202020202020707265207b0a202020202020202020202020202020206e6f646549442e6c656e677468203d3d2036343a20225374616b696e6750726f78792e4e6f6465496e666f2e696e69743a204e6f6465204944206c656e677468206d75737420626520333220627974657320283634206865782063686172616374657273292062757420676f74205c286e6f646549442e6c656e67746829220a202020202020202020202020202020206e6574776f726b696e67416464726573732e6c656e677468203e2030202626206e6574776f726b696e674b65792e6c656e677468203e2030202626207374616b696e674b65792e6c656e677468203e20303a0a202020202020202020202020202020202020202020202020225374616b696e6750726f78792e4e6f6465496e666f2e696e69743a204164647265737320616e64206b657973206d75737420616c6c206265206e6f6e2d656d707479220a2020202020202020202020207d0a20202020202020202020202073656c662e6964203d206e6f646549440a20202020202020202020202073656c662e726f6c65203d20726f6c650a20202020202020202020202073656c662e6e6574776f726b696e6741646472657373203d206e6574776f726b696e67416464726573730a20202020202020202020202073656c662e6e6574776f726b696e674b6579203d206e6574776f726b696e674b65790a20202020202020202020202073656c662e7374616b696e674b6579203d207374616b696e674b65790a20202020202020207d0a202020207d0a0a202020202f2f2f2054686520696e746572666163652074686174206c696d69747320776861742061206e6f6465206f70657261746f722063616e206163636573730a202020202f2f2f2066726f6d20746865207374616b65722077686f2074686579206f70657261746520666f720a2020202061636365737328616c6c292073747275637420696e74657266616365204e6f64655374616b657250726f7879207b0a0a202020202020202061636365737328616c6c292066756e207374616b654e6577546f6b656e7328616d6f756e743a20554669783634290a0a202020202020202061636365737328616c6c292066756e207374616b65556e7374616b6564546f6b656e7328616d6f756e743a20554669783634290a0a202020202020202061636365737328616c6c292066756e2072657175657374556e7374616b696e6728616d6f756e743a20554669783634290a0a202020202020202061636365737328616c6c292066756e20756e7374616b65416c6c28290a0a202020202020202061636365737328616c6c292066756e207769746864726177556e7374616b6564546f6b656e7328616d6f756e743a20554669783634290a0a202020202020202061636365737328616c6c292066756e2077697468647261775265776172646564546f6b656e7328616d6f756e743a20554669783634290a0a202020207d0a0a202020202f2f2f2054686520696e746572666163652074686520646573637269626573207768617420612064656c656761746f722063616e20646f0a2020202061636365737328616c6c292073747275637420696e74657266616365204e6f646544656c656761746f7250726f7879207b0a0a202020202020202061636365737328616c6c292066756e2064656c65676174654e6577546f6b656e7328616d6f756e743a20554669783634290a0a202020202020202061636365737328616c6c292066756e2064656c6567617465556e7374616b6564546f6b656e7328616d6f756e743a20554669783634290a0a202020202020202061636365737328616c6c292066756e2064656c65676174655265776172646564546f6b656e7328616d6f756e743a20554669783634290a0a202020202020202061636365737328616c6c292066756e2072657175657374556e7374616b696e6728616d6f756e743a20554669783634290a0a202020202020202061636365737328616c6c292066756e207769746864726177556e7374616b6564546f6b656e7328616d6f756e743a20554669783634290a0a202020202020202061636365737328616c6c292066756e2077697468647261775265776172646564546f6b656e7328616d6f756e743a20554669783634290a202020207d0a0a202020202f2f2f2054686520696e7465726661636520746861742061206e6f6465206f70657261746f72207075626c6973686573207468656972204e6f64655374616b657250726f7879486f6c6465720a202020202f2f2f20617320696e206f7264657220746f20616c6c6f77206f7468657220746f6b656e20686f6c6465727320746f20696e697469616c697a650a202020202f2f2f207374616b696e672068656c7065722072656c6174696f6e73686970732077697468207468656d0a2020202061636365737328616c6c29207265736f7572636520696e74657266616365204e6f64655374616b657250726f7879486f6c6465725075626c6963207b0a0a202020202020202061636365737328616c6c292066756e206164645374616b696e6750726f7879286e6f646549443a20537472696e672c2070726f78793a207b4e6f64655374616b657250726f78797d290a0a202020202020202061636365737328616c6c292066756e206765744e6f6465496e666f286e6f646549443a20537472696e67293a204e6f6465496e666f3f0a202020207d0a0a202020202f2f2f20546865207265736f757263652074686174206e6f6465206f70657261746f72732073746f726520696e207468656972206163636f756e74730a202020202f2f2f20746f206d616e6167652072656c6174696f6e7368697073207769746820746f6b656e20686f6c646572732077686f20706179207468656d206f66662d636861696e0a202020202f2f2f20696e7374656164206f66207769746820746f6b656e730a2020202061636365737328616c6c29207265736f75726365204e6f64655374616b657250726f7879486f6c6465723a204e6f64655374616b657250726f7879486f6c6465725075626c6963207b0a0a20202020202020202f2f2f204d617073206e6f64652049447320746f20616e7920737472756374207468617420696d706c656d656e747320746865204e6f64655374616b657250726f787920696e746572666163650a20202020202020202f2f2f20616c6c6f7773206e6f6465206f70657261746f727320746f20776f726b20776974682075736572732077697468206c6f636b656420746f6b656e730a20202020202020202f2f2f20616e64207769746820756e7374616b656420746f6b656e730a20202020202020206163636573732873656c662920766172207374616b696e6750726f786965733a207b537472696e673a207b4e6f64655374616b657250726f78797d7d0a0a20202020202020202f2f2f204d617073206e6f64652049447320746f204e6f6465496e666f0a20202020202020206163636573732873656c662920766172206e6f6465496e666f3a207b537472696e673a204e6f6465496e666f7d0a0a2020202020202020696e69742829207b0a20202020202020202020202073656c662e7374616b696e6750726f78696573203d207b7d0a20202020202020202020202073656c662e6e6f6465496e666f203d207b7d0a20202020202020207d0a0a20202020202020202f2f2f204e6f6465206f70657261746f722063616c6c73207468697320746f2061646420696e666f2061626f75742061206e6f646520746865790a20202020202020202f2f2f2077616e7420746f2061636365707420746f6b656e7320666f720a2020202020202020616363657373284e6f64654f70657261746f72292066756e206164644e6f6465496e666f286e6f6465496e666f3a204e6f6465496e666f29207b0a202020202020202020202020707265207b0a2020202020202020202020202020202073656c662e6e6f6465496e666f5b6e6f6465496e666f2e69645d203d3d206e696c0a2020202020202020202020207d0a20202020202020202020202073656c662e6e6f6465496e666f5b6e6f6465496e666f2e69645d203d206e6f6465496e666f0a20202020202020207d0a0a20202020202020202f2f2f2052656d6f7665206e6f646520696e666f2069662069742069736e277420696e2075736520616e79206d6f72650a2020202020202020616363657373284e6f64654f70657261746f72292066756e2072656d6f76654e6f6465496e666f286e6f646549443a20537472696e67293a204e6f6465496e666f207b0a20202020202020202020202072657475726e2073656c662e6e6f6465496e666f2e72656d6f7665286b65793a206e6f6465494429210a20202020202020207d0a0a20202020202020202f2f2f205075626c69736865642066756e6374696f6e20746f2067657420616c6c2074686520696e666f20666f722061207370656369666963206e6f64652049440a202020202020202061636365737328616c6c292066756e206765744e6f6465496e666f286e6f646549443a20537472696e67293a204e6f6465496e666f3f207b0a20202020202020202020202072657475726e2073656c662e6e6f6465496e666f5b6e6f646549445d0a20202020202020207d0a0a20202020202020202f2f2f205075626c69736865642066756e6374696f6e20666f72206120746f6b656e20686f6c6465722077686f20686173207369676e65642075700a20202020202020202f2f2f20746865206e6f6465206f70657261746f722773204e6f6465496e666f20746f206f7065726174652061206e6f64650a20202020202020202f2f2f20546865792073746f726520746865697220604e6f64655374616b657250726f787960206865726520746f20616c6c6f7720746865206e6f64650a20202020202020202f2f2f206f70657261746f7220746f20706572666f726d20736f6d65207374616b696e6720616374696f6e7320616c736f0a202020202020202061636365737328616c6c292066756e206164645374616b696e6750726f7879286e6f646549443a20537472696e672c2070726f78793a207b4e6f64655374616b657250726f78797d29207b0a202020202020202020202020707265207b0a2020202020202020202020202020202073656c662e7374616b696e6750726f786965735b6e6f646549445d203d3d206e696c0a2020202020202020202020207d0a20202020202020202020202073656c662e7374616b696e6750726f786965735b6e6f646549445d203d2070726f78790a20202020202020207d0a0a20202020202020202f2f2f20546865206e6f6465206f70657261746f722063616e2063616c6c207468652072656d6f76655374616b696e6750726f78792066756e6374696f6e0a20202020202020202f2f2f20746f2072656d6f76652061207374616b696e672070726f7879206966206974206973206e6f206c6f6e676572206e65656465640a2020202020202020616363657373284e6f64654f70657261746f72292066756e2072656d6f76655374616b696e6750726f7879286e6f646549443a20537472696e67293a207b4e6f64655374616b657250726f78797d207b0a202020202020202020202020707265207b0a2020202020202020202020202020202073656c662e7374616b696e6750726f786965735b6e6f646549445d20213d206e696c0a2020202020202020202020207d0a0a20202020202020202020202072657475726e2073656c662e7374616b696e6750726f786965732e72656d6f7665286b65793a206e6f6465494429210a20202020202020207d0a0a20202020202020202f2f2f20426f72726f77206120227265666572656e63652220746f20746865207374616b696e672070726f787920736f207374616b696e67206f7065726174696f6e730a20202020202020202f2f2f2063616e20626520706572666f726d656420776974682069740a2020202020202020616363657373284e6f64654f70657261746f72292066756e20626f72726f775374616b696e6750726f7879286e6f646549443a20537472696e67293a207b4e6f64655374616b657250726f78797d3f207b0a20202020202020202020202072657475726e2073656c662e7374616b696e6750726f786965735b6e6f646549445d0a20202020202020207d0a202020207d0a0a202020202f2f2f204372656174652061206e65772070726f787920686f6c64657220666f722061206e6f6465206f70657261746f720a2020202061636365737328616c6c292066756e2063726561746550726f7879486f6c64657228293a20404e6f64655374616b657250726f7879486f6c646572207b0a202020202020202072657475726e203c2d20637265617465204e6f64655374616b657250726f7879486f6c64657228290a202020207d0a0a20202020696e69742829207b0a202020202020202073656c662e4e6f64654f70657261746f724361706162696c69747953746f7261676550617468203d202f73746f726167652f6e6f64654f70657261746f720a202020202020202073656c662e4e6f64654f70657261746f724361706162696c6974795075626c696350617468203d202f7075626c69632f6e6f64654f70657261746f720a202020207d0a7d0a" + } +]