[OOPS! BAD] Circles with sbt-ethereum II: Circles by hand

This post has been superceded; please read http://www.sbt-ethereum.io/blog/2021/03/23/Circles-with-sbt-ethereum-II-Circles-by-hand-redux.html instead.

This (old, bad) version of the tutorial was performed against sbt-ethereum 0.5.1, which contained a serious bug in its handling of ABIs. That bug led to a bunch of mistaken inferences in this version of the tutorial.

The errors are scratched out and explained in the text below, but you are probably better off just reading the expanded, corrected version.


In the previous post, we discussed at a high level what Circles is. Here we’ll go through the exercise of creating a Circles identity by hand with sbt-ethereum.

The web-app is weird

Our command-line adventure will be very, very different from the experience the Circles web application encourages of users. (See https://joincircles.net/ and https://circles.garden/.) The UI works to hide or abstract nearly all the details of working with an Ethereum-ish blockchain application. Users via the web UI don’t use a browser-based crypto wallet like Metamask. Instead, they sign up as for a Web 2.0 application with an e-mail address and username. A private key is then generated for the user, presented as a BIP-39-style list of words.

An address — the user’s identity — is also defined for each user, but that address is not the same address as that for which the private key was generated. Instead it is as address to which a Gnosis Safe contract (or really a proxy thereof) can eventually be deployed via the EVM CREATE2 opcode. eventually. Eventually.

But, because in the web application Circles (or Gnosis, or someone) is handling the gas costs for user transactions, it had to be built with a degree of caution. If any signup provoked smart contract creations or transactions, miscreants could force arbitrary expenses on the payer just by spoofing new users. To prevent this, the Circles requires new users to become trusted by at least three existing users before their identity (the Gnosis Safe proxy) is actually materialized on the blockchain, along with their own ERC-20 token (the “me-coin”) in which they’ll receive their UBI.

That all makes sense, from the perspective of a service provider eating all the transaction costs but trying to protect itself. But it’ll cause us a bit of grief. We’ll pay for our own gas in this exercise, so we’ll get our own UBI-accruing token on the blockchain immediately. But we won’t be able to enter into trust relationships with accounts newly created by the web UI. Those accounts will be invisible to us, until they manage to get three trust relationships established via the web UI, and the machinery behind the web UI finally deigns to create their identity on the blockchain.

Update: This is not right, and reflects a dangerous bug I likely introduced in sbt-ethereum 0.5.0, when I reworked the ABI representation. Martin Koeppelmann pointed out that only the truster’s registration status is verified, not the trustees. My attempts to trust untrusted identities failed due to the ABI bug in sbt-ethereum. There will be an sbt-ethereum 0.5.2 imminently, then I will further revise this post.

Circles contracts

Behind the Circles application sits three contracts on the xDAI blockchain. Pretty much the only place I found the addresses of these contracts documented is in this tweet. The thre contracts are…

  1. The Hub @ 0x29b9a7fBb8995b2423a71cC17cf9810798F6C543: This is the core of the Circles application, the smart contract that tracks identities and trust relationships, and that launches token contracts for each Circles identity. We will interact with this contract. (We’ve reproduced its full source code as an appendix to this post.)
  2. The Proxy Factory @ 0x8b4404DE0CaECE4b966a9959f134f0eFDa636156: This contract is invoked by the middleware / web-UI to create proxy Gnosis Safe contracts, representing uder identities.
  3. The Master Gnosis Safe @ 0x2CB0ebc503dE87CFD8f0eCEED8197bF7850184ae: Identities are efficiently implemented as tiny proxies to a Gnosis Safe implementation, and this is that implementation. Operations on the contracts that represent users happen via DELEGATECALL to this master implementation.

Note: When I first examined the hub on the xDAI block explorer, I thought it must be misidentified. Transactions involving it seemed too few and infrequent. But that’s not right. Since nearly all activity involving the hub is initiated by a user identity, which are nearly all Gnosis Safe contracts, the calls to hub methods are treated as internal transactions, of which there are plenty.

Circles by hand

If you want to play along, you’ll need to have set up your sbt-ethereum environment to work on the xDAI blockchain. Please see previous posts to get started on xDAI, and to give yourself some xDAI to fund transactions.

Now we can get started. First, let’s start up an sbt-ethereum session, get onto the xDAI chain, and check out our environment. (We’ve previously set a node URL from xDAI’s Chain ID, whichis 100.)

sbt:eth-command-line> ethNodeChainIdOverride 100
[info] The chain ID has been overridden to 100.
[info] The session is now active on chain with ID 100, with node URL 'https://rpc.xdaichain.com/'.
[info] The current session sender is '0x72a8a15ECa1f824ADE35cdEB2148223402f23448' (with aliases ['default-sender','testing-xDAI'] on chain with ID 100).
[info] The current default gas price according to your node is 1 gwei. (THIS MAY CHANGE AT ANY TIME.)
[info] Refreshing caches.
[success] Total time: 0 s, completed Feb 22, 2021, 2:56:39 AM

sbt:eth-command-line> eth
[info] The session is now active on chain with ID 100, with node URL 'https://rpc.xdaichain.com/'.
[info] The current session sender is '0x72a8a15ECa1f824ADE35cdEB2148223402f23448' (with aliases ['default-sender','testing-xDAI'] on chain with ID 100).
[info] The current default gas price according to your node is 1 gwei. (THIS MAY CHANGE AT ANY TIME.)
[success] Total time: 0 s, completed Feb 22, 2021, 2:56:46 AM

Cool.

Prepare to work with the Circles hub

Before we can do much with Circles we’ll need to import the ABI for its core contract, the hub. When we’re working on the Ethereum main chain, we can often automatically import ABIs from Etherscan. We can’t do that for contracts on the xDAI blockchain. Instead, we browse the xDAI Blockscout to find the verified contract ABI, and paste that into the console:

sbt:eth-play> ethContractAbiImport 0x29b9a7fBb8995b2423a71cC17cf9810798F6C543
An Etherscan API key has been set. Would you like to try to import the ABI for this address from Etherscan? [y/n] n
Contract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period"Contract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","namContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","namContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","namContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","namContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"typContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"funContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"funContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inpuContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inpuContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","staContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMuContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMuContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods",Contract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","Contract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","Contract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","nameContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":Contract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":Contract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":Contract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"periods","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pow","inputs":[{"type":"uint256","name":"base","internalType":"uint256"},Contract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"periods","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pow","inputs":[{"type":"uint256","name":"base","internalType":"uint256"},{"type":"uint256","name":"exponent","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"seen","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"noContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"periods","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pow","inputs":[{"type":"uint256","name":"base","internalType":"uint256"},{"type":"uint256","name":"exponent","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"seen","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"noContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"periods","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pow","inputs":[{"type":"uint256","name":"base","internalType":"uint256"},{"type":"uint256","name":"exponent","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"seen","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"signup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"signupBonus","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"Contract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"periods","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pow","inputs":[{"type":"uint256","name":"base","internalType":"uint256"},{"type":"uint256","name":"exponent","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"seen","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"signup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"signupBonus","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"timeout","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"nameContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"periods","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pow","inputs":[{"type":"uint256","name":"base","internalType":"uint256"},{"type":"uint256","name":"exponent","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"seen","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"signup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"signupBonus","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"timeout","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"nameContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"periods","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pow","inputs":[{"type":"uint256","name":"base","internalType":"uint256"},{"type":"uint256","name":"exponent","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"seen","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"signup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"signupBonus","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"timeout","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"nameContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"periods","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pow","inputs":[{"type":"uint256","name":"base","internalType":"uint256"},{"type":"uint256","name":"exponent","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"seen","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"signup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"signupBonus","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"timeout","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"nameContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"periods","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pow","inputs":[{"type":"uint256","name":"base","internalType":"uint256"},{"type":"uint256","name":"exponent","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"seen","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"signup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"signupBonus","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"timeout","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"nameContract ABI: [{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"uint256","name":"_inflation","internalType":"uint256"},{"type":"uint256","name":"_period","internalType":"uint256"},{"type":"string","name":"_symbol","internalType":"string"},{"type":"string","name":"_name","internalType":"string"},{"type":"uint256","name":"_signupBonus","internalType":"uint256"},{"type":"uint256","name":"_initialIssuance","internalType":"uint256"},{"type":"uint256","name":"_timeout","internalType":"uint256"}]},{"type":"event","name":"HubTransfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"OrganizationSignup","inputs":[{"type":"address","name":"organization","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Signup","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Trust","inputs":[{"type":"address","name":"canSendTo","internalType":"address","indexed":true},{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"limit","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"checkSendLimit","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"src","internalType":"address"},{"type":"address","name":"dest","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployedAt","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"divisor","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflate","inputs":[{"type":"uint256","name":"_initial","internalType":"uint256"},{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"inflation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"initialIssuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"issuanceByStep","inputs":[{"type":"uint256","name":"_periods","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"limits","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"organizationSignup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"organizations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"period","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"periods","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pow","inputs":[{"type":"uint256","name":"base","internalType":"uint256"},{"type":"uint256","name":"exponent","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"seen","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"signup","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"signupBonus","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"timeout","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"tokenToUser","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferThrough","inputs":[{"type":"address[]","name":"tokenOwners","internalType":"address[]"},{"type":"address[]","name":"srcs","internalType":"address[]"},{"type":"address[]","name":"dests","internalType":"address[]"},{"type":"uint256[]","name":"wads","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"trust","inputs":[{"type":"address","name":"user","internalType":"address"},{"type":"uint256","name":"limit","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract Token"}],"name":"userToToken","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"seen","internalType":"bool"},{"type":"uint256","name":"sent","internalType":"uint256"},{"type":"uint256","name":"received","internalType":"uint256"}],"name":"validation","inputs":[{"type":"address","name":"","internalType":"address"}]}]
[info] A default ABI is now known for the contract at address 0x29b9a7fBb8995b2423a71cC17cf9810798F6C543
[info] Refreshing caches.
[success] Total time: 13 s, completed Feb 22, 2021, 3:37:23 AM

Okay. Let’s give ourselves a human-friendly alias for the hub address 0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 as well.

sbt:eth-command-line> ethAddressAliasSet gnosis-circles-hub 0x29b9a7fBb8995b2423a71cC17cf9810798F6C543
[info] Alias 'gnosis-circles-hub' now points to address '0x29b9a7fBb8995b2423a71cC17cf9810798F6C543' (for chain with ID 100).
[info] Refreshing caches.
[success] Total time: 32 s, completed Feb 22, 2021, 3:38:25 AM

Looks good. Let’s see if we can read stuff from the contract.

sbt:eth-command-line> ethTransactionView gnosis-circles-hub <tab>
checkSendLimit    deployedAt        divisor           inflate           inflation         initialIssuance   issuance          issuanceByStep    limits            name              organizations     period            periods           
pow               seen              signupBonus       symbol            timeout           tokenToUser       userToToken       validation        ​                  
sbt:eth-command-line> ethTransactionView gnosis-circles-hub period
[info] The function 'period' yields 1 result.
[info]  + Result 1 of type 'uint256' is 31556952
[success] Total time: 0 s, completed Feb 22, 2021, 3:39:45 AM

Yes we can!

Define and fund our Circles identity

We’re going to want to define an identity which will signup for Circles, and get its own ERC-20 “me-coin“ contract, which over time will receive a “UBI” (or alternatively, a steadily increasing issuance limit). Rather than use our existing testing-xDAI address (set up previously), we’ll use ethKeystoreWalletV3Create to create a new identity, and give it the alias circles-identity.

sbt:eth-command-line> ethKeystoreWalletV3Create
[info] Generated keypair for address '0x647E68F4BCBC843F39c80bb02da96dD13308f657'
[info] Generating V3 wallet, algorithm=scrypt, n=262144, r=8, p=1, dklen=32
Enter passphrase for new wallet: ************************
Please retype to confirm: ************************
[info] Wallet generated into sbt-ethereum shoebox: '/Users/swaldman/Library/Application Support/sbt-ethereum'. Please backup, via 'ethShoeboxBackup' or manually.
[info] Consider validating the wallet using 'ethKeystoreWalletV3Validate 0x647E68F4BCBC843F39c80bb02da96dD13308f657'.
Would you like to define an alias for address '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (on chain with ID 100)? [y/n] y
Please enter an alias for address '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (on chain with ID 100): circles-identity
[info] Alias 'circles-identity' now points to address '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (for chain with ID 100).
[info] Refreshing caches.
[success] Total time: 72 s (01:12), completed Feb 22, 2021, 3:41:50 AM

Note: This identity is quite different from the one the Circles web application would have created. It is an externally-owned account, rather than a proxied Gnosis Safe contract. But the hub’s logic treats an Ethereum address as an identity. The hub doesn’t actually care what kind of address an identity uses.

We’ll want to sign up with the Circles hub using our new identity, circles-identity as the protagonist, i.e. transaction sender. So we’ll need to fund that account. We send some “ether” (really xDAI, on this xDAI chain) from our already-funded testing-xDAI account:

sbt:eth-command-line> ethTransactionEtherSend circles-identity 1 ether

==> T R A N S A C T I O N   S I G N A T U R E   R E Q U E S T
==>
==> The transaction would be a message with...
==>   To:    0x647E68F4BCBC843F39c80bb02da96dD13308f657 (with aliases ['circles-identity'] on chain with ID 100)
==>   From:  0x72a8a15ECa1f824ADE35cdEB2148223402f23448 (with aliases ['default-sender','testing-xDAI'] on chain with ID 100)
==>   Data:  None
==>   Value: 1 etherine / Compile / ethTransactionEtherSend 0s
==>
==> The nonce of the transaction would be 0.
==>
==> $$$ The transaction you have requested could use up to 25200 units of gas.
==> $$$ You would pay 1 gwei for each unit of gas, for a maximum cost of 0.0000252 ether.
==> $$$ (No USD value could be determined for ETH on chain with ID 100 from Coinbase).
==> $$$ You would also send 1 etherfor a maximum total cost of 1.0000252 ether.

Would you like to sign this transaction? [y/n] y

[info] Unlocking address '0x72a8a15ECa1f824ADE35cdEB2148223402f23448' (with aliases ['default-sender','testing-xDAI'] on chain with ID 100).
Enter passphrase or hex private key for address '0x72a8a15ECa1f824ADE35cdEB2148223402f23448': *******************
[info] Sending 1000000000000000000 wei to address '0x647E68F4BCBC843F39c80bb02da96dD13308f657' in transaction with hash '0x3c4adf988d24f5bdf4e0b0ec7fab19c258083edddce1389ad1faa85c1d892242'.
[info] Waiting for the transaction to be mined (will wait up to 5 minutes).
[info] Transaction Receipt:
[info]        Transaction Hash:    0x3c4adf988d24f5bdf4e0b0ec7fab19c258083edddce1389ad1faa85c1d892242
[info]        Transaction Index:   0
[info]        Transaction Status:  SUCCEEDED
[info]        Block Hash:          0x8a5967394232bd9e58f7fc49e3b0473a4cfeb3ded87c2468d27e26cde041372b
[info]        Block Number:        14671877
[info]        From:                0x72a8a15ECa1f824ADE35cdEB2148223402f23448
[info]        To:                  0x647E68F4BCBC843F39c80bb02da96dD13308f657
[info]        Cumulative Gas Used: 21000
[info]        Gas Used:            21000
[info]        Contract Address:    None
[info]        Logs:                None
[info]        Events:              None
[info] Ether sent.
[success] Total time: 46 s, completed Feb 22, 2021, 3:43:00 AM

Great!

Sign up for Circles as our new identity

Now that circles-identity exists and is funded, let’s assume the role. Let’s make that account our new session sender:

sbt:eth-command-line> ethAddressSenderOverride circles-identity
[info] Sender override set to '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (on chain with ID 100, aliases ['circles-identity'])).
[success] Total time: 0 s, completed Feb 22, 2021, 3:43:12 AM

Okay. Now let’s sign up with the hub.

sbt:eth-command-line> ethTransactionInvoke gnosis-circles-hub <tab>
organizationSignup   signup               transferThrough      trust                ​                     
sbt:eth-command-line> ethTransactionInvoke gnosis-circles-hub signup

==> T R A N S A C T I O N   S I G N A T U R E   R E Q U E S T
==>
==> The transaction would be a message with...
==>   To:    0x29b9a7fBb8995b2423a71cC17cf9810798F6C543 (with aliases ['gnosis-circles-hub'] on chain with ID 100)
==>   From:  0x647E68F4BCBC843F39c80bb02da96dD13308f657 (with aliases ['circles-identity'] on chain with ID 100)
==>   Data:  0xb7bc0f73
==>   Value: 0 etherine / Compile / ethTransactionInvoke 0s
==>
==> According to the ABI currently associated with the 'to' address, this message would amount to the following method call...
==>   Function called: signup()
==>
==> The nonce of the transaction would be 0.
==>
==> $$$ The transaction you have requested could use up to 1472815 units of gas.
==> $$$ You would pay 1 gwei for each unit of gas, for a maximum cost of 0.001472815 ether.
==> $$$ (No USD value could be determined for ETH on chain with ID 100 from Coinbase).

Would you like to sign this transaction? [y/n] y

[info] Unlocking address '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (with aliases ['circles-identity'] on chain with ID 100).
Enter passphrase or hex private key for address '0x647E68F4BCBC843F39c80bb02da96dD13308f657': ************************
[info] Called function 'signup', with args '', sending 0 wei to address '0x29b9a7fBb8995b2423a71cC17cf9810798F6C543' in transaction with hash '0x1aefc8917e2bed0d4c1b55d9ef825666fecfe9d98e7103525bed165a8233e37f'.
[info] Waiting for the transaction to be mined (will wait up to 5 minutes).
[info] Transaction Receipt:
[info]        Transaction Hash:    0x1aefc8917e2bed0d4c1b55d9ef825666fecfe9d98e7103525bed165a8233e37f
[info]        Transaction Index:   4
[info]        Transaction Status:  SUCCEEDED
[info]        Block Hash:          0xdcaaa4e17fa0f11e6e76661925daf7a6d18e9992cfffe1d5acf51154de712622
[info]        Block Number:        14671897
[info]        From:                0x647E68F4BCBC843F39c80bb02da96dD13308f657
[info]        To:                  0x29b9a7fBb8995b2423a71cC17cf9810798F6C543
[info]        Cumulative Gas Used: 3969762
[info]        Gas Used:            1227346
[info]        Contract Address:    None
[info]        Logs:                0 => EthLogEntry [source=0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74] (
[info]                                    topics=[
[info]                                      0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,
[info]                                      0x0000000000000000000000000000000000000000000000000000000000000000,
[info]                                      0x000000000000000000000000647e68f4bcbc843f39c80bb02da96dd13308f657
[info]                                    ],
[info]                                    data=000000000000000000000000000000000000000000000002b5e3af16b1880000
[info]                                  ),
[info]                             1 => EthLogEntry [source=0x29b9a7fBb8995b2423a71cC17cf9810798F6C543] (
[info]                                    topics=[
[info]                                      0xe60c754dd8ab0b1b5fccba257d6ebcd7d09e360ab7dd7a6e58198ca1f57cdcec,
[info]                                      0x000000000000000000000000647e68f4bcbc843f39c80bb02da96dd13308f657,
[info]                                      0x000000000000000000000000647e68f4bcbc843f39c80bb02da96dd13308f657
[info]                                    ],
[info]                                    data=0000000000000000000000000000000000000000000000000000000000000064
[info]                                  ),
[info]                             2 => EthLogEntry [source=0x29b9a7fBb8995b2423a71cC17cf9810798F6C543] (
[info]                                    topics=[
[info]                                      0x358ba8f768af134eb5af120e9a61dc1ef29b29f597f047b555fc3675064a0342,
[info]                                      0x000000000000000000000000647e68f4bcbc843f39c80bb02da96dd13308f657
[info]                                    ],
[info]                                    data=0000000000000000000000006b378db654ba05395d7615be0f07ac1b3cc9ac74
[info]                                  )
[info]        Events:              0 => Anonymous Event [source=0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74],
[info]                             1 => Anonymous Event [source=0x29b9a7fBb8995b2423a71cC17cf9810798F6C543],
[info]                             2 => Signup [source=0x29b9a7fBb8995b2423a71cC17cf9810798F6C543] (
[info]                                    token (of type address): 0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74,
[info]                                    user (of type address): 0x647E68F4BCBC843F39c80bb02da96dD13308f657
[info]                                  )
[success] Total time: 50 s, completed Feb 22, 2021, 3:44:40 AM

Okay! We are all signed up.

Working with our “me-coin”

Looking at the transaction above, it emitted a Signup event in which we can see the address of our new ERC-20 token contract, 0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74. Let’s give that address an alias.

sbt:eth-command-line> ethAddressAliasSet circles-token 0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74
[info] Alias 'circles-token' now points to address '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (for chain with ID 100).
[info] Refreshing caches.
[success] Total time: 0 s, completed Feb 22, 2021, 3:46:20 AM

That should be an ERC-20 token, so let’s use sbt-ethereum‘s built-in erc20Summary task to check it out.

sbt:eth-command-line> erc20Summary circles-token
[info] ERC20 Summary, token contract at '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100):
[info]   Self-Reported Name:   Circles
[info]   Self-Reported Symbol: CRC
[info]   Decimals:             18
[info]   Total Supply:         50 tokens (50000000000000000000 atoms)
[success] Total time: 0 s, completed Feb 22, 2021, 3:47:42 AM

Looks good!

This should be a perfectly normal ERC-20 token. It will have some special functionality — most importantly an update method through which the token owner, circles-token, can receive its “UBI”, and the capacity to call transferThrough on the hub, which restricts transfers according to trust relationships and emits a special HubTransfer event. But we can use our new token just like a plain old ERC-20 too. Let’s give that a try:

sbt:eth-command-line> erc20Transfer circles-token testing-xDAI 1
[warn] For the ERC20 token with contract address '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100)...
[warn]   you would transfer 1 tokens, which (with 18 decimals) translates to 1000000000000000000 atoms.
[warn] The transfer would be 
[warn]   From: '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (with aliases ['circles-identity'] on chain with ID 100)
[warn]   To:   '0x72a8a15ECa1f824ADE35cdEB2148223402f23448' (with aliases ['default-sender','testing-xDAI'] on chain with ID 100)
[warn] You are calling the 'transfer' function on the contract at '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100).
[warn] THIS FUNCTION COULD DO ANYTHING. 
[warn] Make sure that you trust that the token contract does only what you intend, and carefully verify the transaction cost before approving the ultimate transaction.
Continue? [y/n] y

==> T R A N S A C T I O N   S I G N A T U R E   R E Q U E S T
==>
==> The transaction would be a message with...
==>   To:    0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74 (with aliases ['circles-token'] on chain with ID 100)
==>   From:  0x647E68F4BCBC843F39c80bb02da96dD13308f657 (with aliases ['circles-identity'] on chain with ID 100)
==>   Data:  0xa9059cbb00000000000000000000000072a8a15eca1f824ade35cdeb2148223402f234480000000000000000000000000000000000000000000000000de0b6b3a7640000
==>   Value: 0 ether
==>
==> According to the ABI currently associated with the 'to' address, this message would amount to the following method call...
==>   Function called: transfer(address,uint256)
==>     Arg 1 [name=to, type=address]: 0x72a8a15ECa1f824ADE35cdEB2148223402f23448
==>     Arg 2 [name=tokens, type=uint256]: 1000000000000000000
==>
==> The nonce of the transaction would be 1.
==>
==> $$$ The transaction you have requested could use up to 63421 units of gas.
==> $$$ You would pay 1 gwei for each unit of gas, for a maximum cost of 0.000063421 ether.
==> $$$ (No USD value could be determined for ETH on chain with ID 100 from Coinbase).

Would you like to sign this transaction? [y/n] y

Using sender address '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (with aliases ['circles-identity'] on chain with ID 100), which is already unlocked.
Is that okay? [y/n] y

[info] ERC20 Transfer, Token Contract '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100):
[info]   --> Sent 1 tokens (1000000000000000000 atoms)
[info]   -->   from '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (with aliases ['circles-identity'] on chain with ID 100)
[info]   -->   to '0x72a8a15ECa1f824ADE35cdEB2148223402f23448' (with aliases ['default-sender','testing-xDAI'] on chain with ID 100)
[info] Waiting for the transaction to be mined (will wait up to 5 minutes).
[info] Transaction Receipt:
[info]        Transaction Hash:    0x007d3033451439173c16a71a0fb79625da4a0a9c46ca8f758898928a872cc61c
[info]        Transaction Index:   5
[info]        Transaction Status:  SUCCEEDED
[info]        Block Hash:          0x8186dd70b8b3171c4005c4cae7e9ee5ed602b544bea51ec5b848b40f626ede8f
[info]        Block Number:        14671948
[info]        From:                0x647E68F4BCBC843F39c80bb02da96dD13308f657
[info]        To:                  0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74
[info]        Cumulative Gas Used: 1342759
[info]        Gas Used:            51350
[info]        Contract Address:    None
[info]        Logs:                0 => EthLogEntry [source=0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74] (
[info]                                    topics=[
[info]                                      0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,
[info]                                      0x000000000000000000000000647e68f4bcbc843f39c80bb02da96dd13308f657,
[info]                                      0x00000000000000000000000072a8a15eca1f824ade35cdeb2148223402f23448
[info]                                    ],
[info]                                    data=0000000000000000000000000000000000000000000000000de0b6b3a7640000
[info]                                  )
[info]        Events:              0 => Transfer [source=0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74] (
[info]                                    from (of type address): 0x647E68F4BCBC843F39c80bb02da96dD13308f657,
[info]                                    to (of type address): 0x72a8a15ECa1f824ADE35cdEB2148223402f23448,
[info]                                    tokens (of type uint256): 1000000000000000000
[info]                                  )
[success] Total time: 22 s, completed Feb 22, 2021, 3:49:05 AM

We’ve successfully sent one token from circles-identity (which presumably owned all 50 of the initial total supply) to testing-xDAI. We expect circles-identity to now have a balance of only 49 tokens, and testing-xDAI to have a balance of one token. First let’s check circles-identity, which is the default account, since it’s our current session sender:

sbt:eth-command-line> erc20Balance circles-token
[info] For ERC20 Token Contract '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100), with 18 decimals...
[info]   For Address '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (with aliases ['circles-identity'] on chain with ID 100))...
[info]     Balance: 49 tokens (which corresponds to 49000000000000000000 atoms)
[success] Total time: 0 s, completed Feb 22, 2021, 3:49:19 AM

49 tokens as expected! Now let’s check testing-xDAI‘s balance (explicitly):

sbt:eth-command-line> erc20Balance circles-token testing-xDAI
[info] For ERC20 Token Contract '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100), with 18 decimals...
[info]   For Address '0x72a8a15ECa1f824ADE35cdEB2148223402f23448' (with aliases ['default-sender','testing-xDAI'] on chain with ID 100))...
[info]     Balance: 1 tokens (which corresponds to 1000000000000000000 atoms)
[success] Total time: 0 s, completed Feb 22, 2021, 3:49:24 AM

testing-xDAI now has one token, as expected.

We don’t actually want testing-xDAI to have one of these tokens, so let’s send it back, and recheck the balances. We first become testing-xDAI, then send, then check.

sbt:eth-command-line> ethAddressSenderOverride testing-xDAI
[info] Sender override set to '0x72a8a15ECa1f824ADE35cdEB2148223402f23448' (on chain with ID 100, aliases ['default-sender','testing-xDAI'])).
[success] Total time: 0 s, completed Feb 22, 2021, 3:49:38 AM
sbt:eth-command-line> erc20Transfer circles-token circles-identity 1
[warn] For the ERC20 token with contract address '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100)...
[warn]   you would transfer 1 tokens, which (with 18 decimals) translates to 1000000000000000000 atoms.
[warn] The transfer would be 
[warn]   From: '0x72a8a15ECa1f824ADE35cdEB2148223402f23448' (with aliases ['default-sender','testing-xDAI'] on chain with ID 100)
[warn]   To:   '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (with aliases ['circles-identity'] on chain with ID 100)
[warn] You are calling the 'transfer' function on the contract at '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100).
[warn] THIS FUNCTION COULD DO ANYTHING. 
[warn] Make sure that you trust that the token contract does only what you intend, and carefully verify the transaction cost before approving the ultimate transaction.
Continue? [y/n] y

==> T R A N S A C T I O N   S I G N A T U R E   R E Q U E S T
==>
==> The transaction would be a message with...
==>   To:    0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74 (with aliases ['circles-token'] on chain with ID 100)
==>   From:  0x72a8a15ECa1f824ADE35cdEB2148223402f23448 (with aliases ['default-sender','testing-xDAI'] on chain with ID 100)
==>   Data:  0xa9059cbb000000000000000000000000647e68f4bcbc843f39c80bb02da96dd13308f6570000000000000000000000000000000000000000000000000de0b6b3a7640000
==>   Value: 0 ether
==>
==> According to the ABI currently associated with the 'to' address, this message would amount to the following method call...
==>   Function called: transfer(address,uint256)
==>     Arg 1 [name=to, type=address]: 0x647E68F4BCBC843F39c80bb02da96dD13308f657
==>     Arg 2 [name=tokens, type=uint256]: 1000000000000000000
==>
==> The nonce of the transaction would be 1.
==>
==> $$$ The transaction you have requested could use up to 43620 units of gas.
==> $$$ You would pay 1 gwei for each unit of gas, for a maximum cost of 0.00004362 ether.
==> $$$ (No USD value could be determined for ETH on chain with ID 100 from Coinbase).

Would you like to sign this transaction? [y/n] y

[info] Unlocking address '0x72a8a15ECa1f824ADE35cdEB2148223402f23448' (with aliases ['default-sender','testing-xDAI'] on chain with ID 100).
Enter passphrase or hex private key for address '0x72a8a15ECa1f824ADE35cdEB2148223402f23448': *******************
[info] ERC20 Transfer, Token Contract '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100):
[info]   --> Sent 1 tokens (1000000000000000000 atoms)
[info]   -->   from '0x72a8a15ECa1f824ADE35cdEB2148223402f23448' (with aliases ['default-sender','testing-xDAI'] on chain with ID 100)
[info]   -->   to '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (with aliases ['circles-identity'] on chain with ID 100)
[info] Waiting for the transaction to be mined (will wait up to 5 minutes).
[info] Transaction Receipt:
[info]        Transaction Hash:    0x39d2345858685ec8315e99b3215a21246a01c69c0af319babc3f199e40805f60
[info]        Transaction Index:   3
[info]        Transaction Status:  SUCCEEDED
[info]        Block Hash:          0xe619abbf080d6b9ac1c7fbbb77e1ad73ae7dc9730c190d2b30971b45d9cb36c8
[info]        Block Number:        14671967
[info]        From:                0x72a8a15ECa1f824ADE35cdEB2148223402f23448
[info]        To:                  0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74
[info]        Cumulative Gas Used: 729291
[info]        Gas Used:            21350
[info]        Contract Address:    None
[info]        Logs:                0 => EthLogEntry [source=0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74] (
[info]                                    topics=[
[info]                                      0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,
[info]                                      0x00000000000000000000000072a8a15eca1f824ade35cdeb2148223402f23448,
[info]                                      0x000000000000000000000000647e68f4bcbc843f39c80bb02da96dd13308f657
[info]                                    ],
[info]                                    data=0000000000000000000000000000000000000000000000000de0b6b3a7640000
[info]                                  )
[info]        Events:              0 => Transfer [source=0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74] (
[info]                                    from (of type address): 0x72a8a15ECa1f824ADE35cdEB2148223402f23448,
[info]                                    to (of type address): 0x647E68F4BCBC843F39c80bb02da96dD13308f657,
[info]                                    tokens (of type uint256): 1000000000000000000
[info]                                  )
[success] Total time: 42 s, completed Feb 22, 2021, 3:50:40 AM
sbt:eth-command-line> erc20Balance circles-token testing-xDAI
[info] For ERC20 Token Contract '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100), with 18 decimals...
[info]   For Address '0x72a8a15ECa1f824ADE35cdEB2148223402f23448' (with aliases ['default-sender','testing-xDAI'] on chain with ID 100))...
[info]     Balance: 0 tokens (which corresponds to 0 atoms)
[success] Total time: 0 s, completed Feb 22, 2021, 3:51:08 AM
sbt:eth-command-line> erc20Balance circles-token circles-identity
[info] For ERC20 Token Contract '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100), with 18 decimals...
[info]   For Address '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (with aliases ['circles-identity'] on chain with ID 100))...
[info]     Balance: 50 tokens (which corresponds to 50000000000000000000 atoms)
[success] Total time: 2 s, completed Feb 22, 2021, 3:51:16 AM

Looks good.

Trust frustrated

Update: This is section is all wrong. You can in fact trust unregistered users. My attempts to do so were failing due to a dangerous bug I likely introduced in sbt-ethereum 0.5.0, when I reworked the ABI representation. There will be an sbt-ethereum 0.5.2 imminently, and then I will revise this post.

It would be fun to start building our web of trust. But I don’t know anybody I can trust. So, I tried making a new Circles identity called @FakeUser0 via the web application. He seems like a trustworthy guy! His profile URL is https://circles.garden/profile/0xb02678607eF6578aDD40781939451Db85edc7330 So maybe I can trust address 0xb02678607eF6578aDD40781939451Db85edc7330? Let’s try it.

sbt:eth-play> ethTransactionInvoke gnosis-circles-hub trust 50 0xb02678607eF6578aDD40781939451Db85edc7330
[error] stack trace is suppressed; run last Compile / ethTransactionInvoke for the full output
[error] (Compile / ethTransactionInvoke) com.mchange.sc.v1.consuela.ethereum.jsonrpc.package$ClientException: revert -- errorCode=-32603; methodName=eth_estimateGas; params=List({"from":"0x647e68f4bcbc843f39c80bb02da96dd13308f657","to":"0x29b9a7fbb8995b2423a71cc17cf9810798f6c543","value":"0x0","data":"0xa5456a2a0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000b02678607ef6578add40781939451db85edc7330"})
[error] Total time: 0 s

I tried to trust that address, but only 50%. It didn’t work. Here’s why. From the Solidity source of the hub:

/// @notice trust a user, calling this means you're able to receive tokens from this user transitively
/// @dev the trust graph is weighted and directed
/// @param user the user to be trusted
/// @param limit the amount this user is trusted, as a percentage of 100
function trust(address user, uint limit) public {
    // only users who have signed up as tokens or organizations can enter the trust graph
    require(address(userToToken[msg.sender]) != address(0) || organizations[msg.sender], "You can only trust people after you've signed up!");
    // you must continue to trust yourself 100%
    require(msg.sender != user, "You can't untrust yourself");
    // organizations can't receive trust since they don't have their own token (ie. there's nothing to trust)
    require(organizations[user] == false, "You can't trust an organization");
    // must a percentage
    require(limit <= 100, "Limit must be a percentage out of 100");
    // organizations don't have a token to base send limits off of, so they can only trust at rates 0 or 100
    if (organizations[msg.sender]) {
        require(limit == 0 || limit == 100, "Trust is binary for organizations");
    }
    _trust(user, limit);
}

Update: Notice that the order in which I entered the arguments when I tried to invoke the trust function — uint then address — is opposite to the ordering of arguments in the actual function. That is my ABI bug.

The first thing the trust(...) method does is insist that the address we wish to trust is an identity already signed up on the blockchain. If it is, it will have its own “me-coin”. So the hub checks the userToToken mapping for a non-zero token address. We can do that ourselves:

Update: This is wrong. Look at the trust method, it checks whether the truster has a registered address, not whether the trustee does. My attempt to call the method failed not due to the trust check, but because of a failure to actually call the method, because the ABI bug I introduced in v0.5.0 inverted the order of the arguments. Zero and one argument functions are fine, but multiargument functions are dangerous and broken until sbt-ethereum v0.5.2

sbt:eth-play> ethTransactionView gnosis-circles-hub userToToken 0xb02678607eF6578aDD40781939451Db85edc7330
[info] The function 'userToToken' yields 1 result.
[info]  + Result 1 of type 'address' is 0x0000000000000000000000000000000000000000
[success] Total time: 0 s

We see, as we described above, that web-app created identities don’t show up on the blockchain, presumably until they’ve been trusted three times within the bland, gasless world of the web-app. Bummer!

Let’s verify that we can find our own token address this way:

sbt:eth-play> ethTransactionView gnosis-circles-hub userToToken circles-identity
[info] The function 'userToToken' yields 1 result.
[info]  + Result 1 of type 'address' is 0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74
[success] Total time: 0 s, completed Mar 15, 2021 4:06:47 PM

sbt:eth-play> ethAddressAliasCheck 0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74
The address '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' is associated with alias 'circles-token'.
[success] Total time: 0 s, completed Mar 15, 2021 4:06:58 PM

In a word, yuh-huh.

Collecting our “UBI”

We let a good bit of time pass, and then restart a new session, switching onto the xDAI blockchain:

sbt:eth-play> ethNodeChainIdOverride 100
[info] A chain ID override had already been set to 100. Nothing to do.
[success] Total time: 0 s, completed Mar 11, 2021 9:51:48 PM

First, let’s check circles-identity‘s current balance of circles-token:

sbt:eth-play> erc20Balance circles-token circles-identity
[info] For ERC20 Token Contract '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100), with 18 decimals...
[info]   For Address '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (with aliases ['circles-identity'] on chain with ID 100))...
[info]     Balance: 50 tokens (which corresponds to 50000000000000000000 atoms)
[success] Total time: 0 s, completed Mar 11, 2021 9:52:17 PM

It’s the same as before, just 50 tokens, we haven’t received any UBI yet. But wait! We’re not supposed to until we call an update method. (See the source code in the appendix, which includes the token contract.)

Since update() is not a standard ERC-20 method, we’ll need to import the ABI for Circles-specific tokens. We can find that on the Circles github site.

Be sure to only capture the ABI part, not the full JSON file, which includes all compilation artifacts!

Unfortunately, what you’ll capture is pretty-printed JSON, including newlines, which we can’t paste into the console to import. So, we find a JSON minifier online, convert it to a compact, newline-free representation. Alternatively, you can just steal it from the example below. However you get it, you’ll need to import it:

sbt:eth-play> ethContractAbiImport circles-token
An Etherscan API key has been set. Would you like to try to import the ABI for this address from Etherscan? [y/n] n
Contract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","typContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","typContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuancContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuancContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":Contract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":Contract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"addreContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"addreContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"Contract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"Contract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"Contract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool",Contract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool",Contract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type"Contract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMuContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMuContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periods","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"vieContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periods","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"vieContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periods","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodsWhenLastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hubDeployedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutabilitContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periods","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodsWhenLastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hubDeployedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutabilitContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periods","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodsWhenLastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hubDeployedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutabilitContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periods","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodsWhenLastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hubDeployedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutabilitContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periods","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodsWhenLastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hubDeployedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutabilitContract ABI: [{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentIssuance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"inflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"time","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"period","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periods","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodsWhenLastTouched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hubDeployedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopped","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"findInflationOffset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"look","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"hubTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
[info] A default ABI is now known for the contract at address 0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74
[info] Refreshing caches.

Now we can see and use methods that are not standard to ERC-20 tokens:

sbt:eth-play> ethTransactionInvoke circles-token <tab>
approve             decreaseAllowance   hubTransfer         increaseAllowance   stop                transfer            transferFrom        update              ​

Let’s call update:

sbt:eth-play> ethTransactionInvoke circles-token update

==> T R A N S A C T I O N   S I G N A T U R E   R E Q U E S T
==>
==> The transaction would be a message with...
==>   To:    0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74 (with aliases ['circles-token'] on chain with ID 100)
==>   From:  0x72a8a15ECa1f824ADE35cdEB2148223402f23448 (with aliases ['default-sender','testing-xDAI'] on chain with ID 100)
==>   Data:  0xa2e62045
==>   Value: 0 ether
==>
==> According to the ABI currently associated with the 'to' address, this message would amount to the following method call...
==>   Function called: update()
==>
==> The nonce of the transaction would be 2.
==>
==> $$$ The transaction you have requested could use up to 90590 units of gas.
==> $$$ You would pay 20 gwei for each unit of gas, for a maximum cost of 0.0018118 ether.
==> $$$ (No USD value could be determined for ETH on chain with ID 100 from Coinbase).

Would you like to sign this transaction? [y/n] y

[info] Unlocking address '0x72a8a15ECa1f824ADE35cdEB2148223402f23448' (with aliases ['default-sender','testing-xDAI'] on chain with ID 100).
Enter passphrase or hex private key for address '0x72a8a15ECa1f824ADE35cdEB2148223402f23448': *******************
[info] Called function 'update', with args '', sending 0 wei to address '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' in transaction with hash '0x4fc758cf1118247ee02280dcf8be5101d0467167fcd947a8c1c21a85309ab9e2'.
[info] Waiting for the transaction to be mined (will wait up to 5 minutes).
[info] Transaction Receipt:
[info]        Transaction Hash:    0x4fc758cf1118247ee02280dcf8be5101d0467167fcd947a8c1c21a85309ab9e2
[info]        Transaction Index:   0
[info]        Transaction Status:  SUCCEEDED
[info]        Block Hash:          0x0632be92685a380762bec506ec618befc0bc1165a017e9ea13b4ce58668c33ff
[info]        Block Number:        14966053
[info]        From:                0x72a8a15ECa1f824ADE35cdEB2148223402f23448
[info]        To:                  0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74
[info]        Cumulative Gas Used: 73924
[info]        Gas Used:            73924
[info]        Contract Address:    None
[info]        Logs:                0 => EthLogEntry [source=0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74] (
[info]                                    topics=[
[info]                                      0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,
[info]                                      0x0000000000000000000000000000000000000000000000000000000000000000,
[info]                                      0x000000000000000000000000647e68f4bcbc843f39c80bb02da96dd13308f657
[info]                                    ],
[info]                                    data=000000000000000000000000000000000000000000000007b353b0431a47eca0
[info]                                  )
[info]        Events:              0 => Transfer [source=0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74] (
[info]                                    from (of type address): 0x0000000000000000000000000000000000000000,
[info]                                    to (of type address): 0x647E68F4BCBC843F39c80bb02da96dD13308f657,
[info]                                    value (of type uint256): 142049074074073164960
[info]                                  )
[success] Total time: 30 s, completed Mar 11, 2021 9:53:31 PM

Note we called update() from testing-xDAI, a pretty much unrelated address, rather than from the circles-identity associated with this token. The token doesn’t care. Anyone can call update().

But now let’s check circles-identity‘s balance:

sbt:eth-play> erc20Balance circles-token circles-identity
[info] For ERC20 Token Contract '0x6B378dB654BA05395D7615Be0F07ac1B3cC9ac74' (with aliases ['circles-token'] on chain with ID 100), with 18 decimals...
[info]   For Address '0x647E68F4BCBC843F39c80bb02da96dD13308f657' (with aliases ['circles-identity'] on chain with ID 100))...
[info]     Balance: 192.04907407407316496 tokens (which corresponds to 192049074074073164960 atoms)
[success] Total time: 0 s, completed Mar 11, 2021 9:53:38 PM

Calling update has left circles-identity richly rewarded. Its balance has gone from 50 tokens to about 192 tokens! Yay UBI!

Conclusion

So, we’ve succeeded “by hand” at creating an identity, funding it on the xDAI block chain, and signing it up for Circles on the hub contract. That generated a new ERC-20 token, of which our registered identity had an initial balance of 50 tokens. But, so long as anybody periodically “touches” the token contract by calling update, we’ve seen that circles-identity‘s balance will grow over time, receiving its “UBI” in its own scrip.

One thing we have not made work is trust. This was due to a dangerous bug in sbt-ethereum v.0.5.0 and v0.5.1. To trust an identity, it must already exist on the xDAI blockchain. But as we’ve seen, accounts newly created on the web-app don’t exist and so can’t be trusted. My attempts to make and trust such an account failed, as have my attempts to trust friends’ Circles identities (who also have not yet been trusted by three identities known to the web-app).

If you have a thrice-trusted, materialized identity on circles (so you are receiving your “UBI”), and you think I should trust you, please let me know your address (or your profile URL that contains it), and I may try!

(I could sign up a new address directly on the hub contract, the way I signed up circles-identity, but I don’t really want to multiply identities, and I want to be user that blockchain-only identities are interoperable with those created by the web-app.)

Appendix: Circles hub source code

Here is the full source code of the Circles hub. It includes the source code of the generated ERC-20 token contracts:

// File: @openzeppelin/contracts/math/SafeMath.sol

pragma solidity ^0.7.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

// File: @openzeppelin/contracts/utils/Address.sol

pragma solidity ^0.7.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// File: contracts/ERC20.sol

// Based on @openzeppelin/contracts/token/ERC20/ERC20.sol

pragma solidity ^0.7.0;



/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */

contract ERC20 {
    using SafeMath for uint256;
    using Address for address;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _symbol;
    uint8 private _decimals;

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() external virtual view returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5,05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
     * called.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() external virtual view returns (uint8) {
        return _decimals;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual returns (bool) {
        _approve(msg.sender, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20};
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public virtual returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);
        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Sets {decimals} to a value other than the default one of 18.
     *
     * WARNING: This function should only be called from the constructor. Most
     * applications that interact with token contracts will not expect
     * {decimals} to ever change, and may work incorrectly if it does.
     */
    function _setupDecimals(uint8 decimals_) internal {
        _decimals = decimals_;
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be to transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
}

// File: contracts/interfaces/HubI.sol

pragma solidity ^0.7.0;

interface HubI {
    function issuance() external view returns (uint256);
    function issuanceByStep(uint256) external view returns (uint256);
    function inflation() external view returns (uint256);
    function divisor() external view returns (uint256);
    function period() external view returns (uint256);
    function periods() external view returns (uint256);
    function signupBonus() external view returns (uint256);
    function pow(uint256, uint256) external view returns (uint256);
    function totalSupply() external view returns (uint256);
    function symbol() external view returns (string memory);
    function name() external view returns (string memory);
    function deployedAt() external view returns (uint256);
    function inflate(uint256, uint256) external view returns (uint256);
    function timeout() external view returns (uint256);
}

// File: contracts/Token.sol

pragma solidity ^0.7.0;




contract Token is ERC20 {
    using SafeMath for uint256;

    uint8 public immutable override decimals = 18;

    uint256 public lastTouched; // the timestamp of the last ubi payout
    address public hub; // the address of the hub this token was deployed through
    address public immutable owner; // the safe that deployed this token
    uint256 public inflationOffset; // the amount of seconds until the next inflation step
    uint256 public currentIssuance; // issanceRate at the time this token was deployed
    bool private manuallyStopped; // true if this token has been stopped by it's owner

    /// @dev modifier allowing function to be only called through the hub
    modifier onlyHub() {
        require(msg.sender == hub);
        _;
    }

    /// @dev modifier allowing function to be only called by the token owner
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }

    constructor(address _owner) {
        require(_owner != address(0));
        owner = _owner;
        hub = msg.sender;
        lastTouched = time();
        inflationOffset = findInflationOffset();
        currentIssuance = HubI(hub).issuance();
        _mint(_owner, HubI(hub).signupBonus());
    }

    /// @notice helper function for block timestamp
    /// @return the block timestamp
    function time() public view returns (uint) {
        return block.timestamp;
    }

    /// @notice helper function for the token symbol
    /// @dev all circles tokens should have the same symbol
    /// @return the token symbol
    function symbol() public view override returns (string memory) {
        return HubI(hub).symbol();
    }

    /// @notice helper function for the token name
    /// @dev all circles tokens should have the same name
    /// @return the token name
    function name() public view returns (string memory) {
        return HubI(hub).name();
    }

    /// @notice helper function for fetching the period length from the hub
    /// @return period length in seconds
    function period() public view returns (uint256) {
        return HubI(hub).period();
    }

    /// @notice helper function for fetching the number of periods from the hub
    /// @return the number of periods since the hub was deployed
    function periods() public view returns (uint256) {
        return HubI(hub).periods();
    }

    /// @notice helper function for fetching the timeout from the hub
    /// @return the number of seconds the token can go without being updated before it's deactivated
    function timeout() public view returns (uint256) {
        return HubI(hub).timeout();
    }

    /// @notice find the inflation step when ubi was last payed out
    /// @dev ie. if ubi was last payed out during the second inflation step, returns two
    /// @return the inflation step by count
    function periodsWhenLastTouched() public view returns (uint256) {
        return (lastTouched.sub(hubDeployedAt())).div(period());
    }

    /// @notice helper functio for getting the hub deployment time
    /// @return the timestamp the hub was deployed at
    function hubDeployedAt() public view returns (uint256) {
        return HubI(hub).deployedAt();
    }

    /// @notice Caution! manually deactivates or stops this token, no ubi will be payed out after this is called
    /// @dev intended for use in case of key loss, system failure, or migration to new contracts
    function stop() public onlyOwner {
        manuallyStopped = true;
    }

    /// @notice checks whether this token has been either stopped manually, or whether it has timed out
    /// @dev combines the manual stop variable with a dead man's switch
    /// @return true is the token is still paying out ubi, otherwise false
    function stopped() public view returns (bool) {
        if (manuallyStopped) return true;
        uint256 secondsSinceLastTouched = time().sub(lastTouched);
        if (secondsSinceLastTouched > timeout()) return true;
        return false;
    }

    /// @notice the amount of seconds until the ubi payout is next inflated
    /// @dev ubi is payed out continuously between inflation steps
    /// @return the amount of seconds until the next inflation step
    function findInflationOffset() public view returns (uint256) {
        // finds the timestamp of the next inflation step, and subtracts the current timestamp
        uint256 nextInflation = ((period().mul(periods().add(1))).add(hubDeployedAt()));
        return nextInflation.sub(time());
    }

    /// @notice checks how much ubi this token holder is owed, but doesn't update their balance
    /// @dev is called in the update method to write the new balance to state, but also useful in wallets
    /// @return how much ubi this token holder is owed
    function look() public view returns (uint256) {
        // don't payout ubi if the token has been deactivated/stopped
        if (stopped()) return 0;
        uint256 payout = 0;
        uint256 clock = lastTouched;
        uint256 offset = inflationOffset;
        uint256 rate = currentIssuance;
        uint256 p = periodsWhenLastTouched();
        // this while loop gets executed only when we're rolling over an inflation step 
        // in the course of a ubi payout aka while we have to pay out ubi for more time
        // than lastTouched + inflationOffset
        while (clock.add(offset) <= time()) {
            // add the remaining offset time to the payout total at the current rate
            payout = payout.add(offset.mul(rate));
            // adjust clock to the timestamp of the next inflation step
            clock = clock.add(offset);
            // the offset is now the length of 1 period
            offset = period();
            // increment the period we are paying out for
            p = p.add(1);
            // find the issuance rate as of the next period
            rate = HubI(hub).issuanceByStep(p);
        }
        // at this point, time() - clock should always be less than 1 period
        uint256 timeSinceLastPayout = time().sub(clock);
        payout = payout.add(timeSinceLastPayout.mul(rate));
        return payout;
    }

    /// @notice receive a ubi payout
    /// @dev this is the method to actually update storage with new token balance
    function update() public {
        uint256 gift = look();
        // does nothing if there's no ubi to be payed out
        if (gift > 0) {
            // update the state variables used to calculate ubi, then mint
            inflationOffset = findInflationOffset();
            lastTouched = time();
            currentIssuance = HubI(hub).issuance();
            _mint(owner, gift);
        }
    }

    /// @notice special method called by the hub to execute a transitive transaction
    /// @param from the address the tokens are being transfered from
    /// @param to the address the tokens are being transferred to
    /// @param amount the amount of tokens to transfer
    function hubTransfer(
        address from, address to, uint256 amount
    ) public onlyHub returns (bool) {
        _transfer(from, to, amount);
    }

    function transfer(address dst, uint wad) public override returns (bool) {
        // this code shouldn't be necessary, but when it's removed the gas estimation methods
        // in the gnosis safe no longer work, still true as of solidity 7.1
        return super.transfer(dst, wad);
    }
}

// File: contracts/Hub.sol

pragma solidity ^0.7.0;



contract Hub {
    using SafeMath for uint256;

    uint256 public immutable inflation; // the inflation rate expressed as 1 + percentage inflation, aka 7% inflation is 107
    uint256 public immutable divisor; // the largest power of 10 the inflation rate can be divided by
    uint256 public immutable period; // the amount of sections between inflation steps
    string public symbol;
    string public name;
    uint256 public immutable signupBonus; // a one-time payout made immediately on signup
    uint256 public immutable initialIssuance; // the starting payout per second, this gets inflated by the inflation rate
    uint256 public immutable deployedAt; // the timestamp this contract was deployed at
    uint256 public immutable timeout; // longest a token can go without a ubi payout before it gets deactivated

    mapping (address => Token) public userToToken;
    mapping (address => address) public tokenToUser;
    mapping (address => bool) public organizations;
    mapping (address => mapping (address => uint256)) public limits;

    event Signup(address indexed user, address token);
    event OrganizationSignup(address indexed organization);
    event Trust(address indexed canSendTo, address indexed user, uint256 limit);
    event HubTransfer(address indexed from, address indexed to, uint256 amount);

    // some data types used for validating transitive transfers
    struct transferValidator {
        bool seen;
        uint256 sent;
        uint256 received;
    }
    mapping (address => transferValidator) public validation;
    address[] public seen;

    constructor(
        uint256 _inflation,
        uint256 _period,
        string memory _symbol,
        string memory _name,
        uint256 _signupBonus,
        uint256 _initialIssuance,
        uint256 _timeout
    ) {
        inflation = _inflation;
        divisor = findDivisor(_inflation);
        period = _period;
        symbol = _symbol;
        name = _name;
        signupBonus = _signupBonus;
        initialIssuance = _initialIssuance;
        deployedAt = block.timestamp;
        timeout = _timeout;
    }

    /// @notice calculates the correct divisor for the given inflation rate
    /// @dev the divisor is used to maintain precision when doing math with percentages
    /// @param _inf the inflation rate
    /// @return the largest power of ten the inflation rate can be divided by
    function findDivisor(uint256 _inf) internal pure returns (uint256) {
        uint256 iter = 0;
        while (_inf.div(pow(10, iter)) > 9) {
            iter += 1;
        }
        return pow(10, iter);
    }

    /// @notice helper function for finding the amount of inflation periods since this hub was deployed
    /// @return the amount of periods since hub was deployed
    function periods() public view returns (uint256) {
        return (block.timestamp.sub(deployedAt)).div(period);
    }

    /// @notice calculates the current issuance rate per second
    /// @dev current issuance is the initial issuance inflated by the amount of inflation periods since the hub was deployed
    /// @return current issuance rate
    function issuance() public view returns (uint256) {
        return inflate(initialIssuance, periods());
    }

    /// @notice finds the inflation rate at a given inflation period
    /// @param _periods the step to calculate the issuance rate at
    /// @return inflation rate as of the given period
    function issuanceByStep(uint256 _periods) public view returns (uint256) {
        return inflate(initialIssuance, _periods);
    }

    /// @notice find the current issuance rate for any initial issuance and amount of periods
    /// @dev this is basically the calculation for compound interest, with some adjustments because of integer math
    /// @param _initial the starting issuance rate
    /// @param _periods the step to calculate the issuance rate as of
    /// @return initial issuance rate as if interest (inflation) has been compounded period times
    function inflate(uint256 _initial, uint256 _periods) public view returns (uint256) {
        // this returns P * (1 + r) ** t - which is a the formula for compound interest if 
        // interest is compounded only once per period
        // in our case, currentIssuanceRate = initialIssuance * (inflation) ** periods
        uint256 q = pow(inflation, _periods);
        uint256 d = pow(divisor, _periods);
        return (_initial.mul(q)).div(d);
    }

    /// @notice signup to this circles hub - create a circles token and join the trust graph
    /// @dev signup is permanent, there's no way to unsignup
    function signup() public {
        // signup can only be called once
        require(address(userToToken[msg.sender]) == address(0), "You can't sign up twice");
        // organizations cannot sign up for a token
        require(organizations[msg.sender] == false, "Organizations cannot signup as normal users");

        Token token = new Token(msg.sender);
        userToToken[msg.sender] = token;
        tokenToUser[address(token)] = msg.sender;
        // every user must trust themselves with a weight of 100
        // this is so that all users accept their own token at all times
        _trust(msg.sender, 100);

        emit Signup(msg.sender, address(token));
    }

    /// @notice register an organization address with the hub and join the trust graph
    /// @dev signup is permanent for organizations too, there's no way to unsignup
    function organizationSignup() public {
        // can't register as an organization if you have a token
        require(address(userToToken[msg.sender]) == address(0), "Normal users cannot signup as organizations");
        // can't register as an organization twice
        require(organizations[msg.sender] == false, "You can't sign up as an organization twice");

        organizations[msg.sender] = true;

        emit OrganizationSignup(msg.sender);
    }

    /// @notice trust a user, calling this means you're able to receive tokens from this user transitively
    /// @dev the trust graph is weighted and directed
    /// @param user the user to be trusted
    /// @param limit the amount this user is trusted, as a percentage of 100
    function trust(address user, uint limit) public {
        // only users who have signed up as tokens or organizations can enter the trust graph
        require(address(userToToken[msg.sender]) != address(0) || organizations[msg.sender], "You can only trust people after you've signed up!");
        // you must continue to trust yourself 100%
        require(msg.sender != user, "You can't untrust yourself");
        // organizations can't receive trust since they don't have their own token (ie. there's nothing to trust)
        require(organizations[user] == false, "You can't trust an organization");
        // must a percentage
        require(limit <= 100, "Limit must be a percentage out of 100");
        // organizations don't have a token to base send limits off of, so they can only trust at rates 0 or 100
        if (organizations[msg.sender]) {
            require(limit == 0 || limit == 100, "Trust is binary for organizations");
        }
        _trust(user, limit);
    }

    /// @dev used internally in both the trust function and signup
    /// @param user the user to be trusted
    /// @param limit the amount this user is trusted, as a percentage of 100
    function _trust(address user, uint limit) internal {
        limits[msg.sender][user] = limit;
        emit Trust(msg.sender, user, limit);
    }

    /// @dev this is an implementation of exponentiation by squares
    /// @param base the base to be used in the calculation
    /// @param exponent the exponent to be used in the calculation
    /// @return the result of the calculation
    function pow(uint256 base, uint256 exponent) public pure returns (uint256) {
        if (base == 0) {
            return 0;
        }
        if (exponent == 0) {
            return 1;
        }
        if (exponent == 1) {
            return base;
        }
        uint256 y = 1;
        while(exponent > 1) {
            if(exponent.mod(2) == 0) {
                base = base.mul(base);
                exponent = exponent.div(2);
            } else {
                y = base.mul(y);
                base = base.mul(base);
                exponent = (exponent.sub(1)).div(2);
            }
        }
        return base.mul(y);
    }

    /// @notice finds the maximum amount of a specific token that can be sent between two users
    /// @dev the goal of this function is to always return a sensible number, it's used to validate transfer throughs, and also heavily in the graph/pathfinding services
    /// @param tokenOwner the safe/owner that the token was minted to
    /// @param src the sender of the tokens
    /// @param dest the recipient of the tokens
    /// @return the amount of tokenowner's token src can send to dest
    function checkSendLimit(address tokenOwner, address src, address dest) public view returns (uint256) {

        // there is no trust
        if (limits[dest][tokenOwner] == 0) {
            return 0;
        }

        // if dest hasn't signed up, they cannot trust anyone
        if (address(userToToken[dest]) == address(0) && !organizations[dest] ) {
            return 0;
        }

        //if the token doesn't exist, it can't be sent/accepted
        if (address(userToToken[tokenOwner]) == address(0)) {
             return 0;
        }

        uint256 srcBalance = userToToken[tokenOwner].balanceOf(src);

        // if sending dest's token to dest, src can send 100% of their holdings
        // for organizations, trust is binary - if trust is not 0, src can send 100% of their holdings
        if (tokenOwner == dest || organizations[dest]) {
            return srcBalance;
        }

        // find the amount dest already has of the token that's being sent
        uint256 destBalance = userToToken[tokenOwner].balanceOf(dest);

        uint256 oneHundred = 100;
        
        // find the maximum possible amount based on dest's trust limit for this token
        uint256 max = (userToToken[dest].balanceOf(dest).mul(limits[dest][tokenOwner])).div(oneHundred);
        
        // if trustLimit has already been overriden by a direct transfer, nothing more can be sent
        if (max < destBalance) return 0;

        uint256 destBalanceScaled = destBalance.mul(oneHundred.sub(limits[dest][tokenOwner])).div(oneHundred);
        
        // return the max amount dest is willing to hold minus the amount they already have
        return max.sub(destBalanceScaled);
    }

    /// @dev builds the validation data structures, called for each transaction step of a transtive transactions
    /// @param src the sender of a single transaction step
    /// @param dest the recipient of a single transaction step
    /// @param wad the amount being passed along a single transaction step
    function buildValidationData(address src, address dest, uint wad) internal {
        // the validation mapping has this format
        // { address: {
        //     seen: whether this user is part of the transaction,
        //     sent: total amount sent by this user,
        //     received: total amount received by this user,
        //    }
        // }
        if (validation[src].seen != false) {
            // if we have seen the addresses, increment their sent amounts
            validation[src].sent = validation[src].sent.add(wad);
        } else {
            // if we haven't, add them to the validation mapping
            validation[src].seen = true;
            validation[src].sent = wad;
            seen.push(src);
        }
        if (validation[dest].seen != false) {
            // if we have seen the addresses, increment their sent amounts
            validation[dest].received = validation[dest].received.add(wad);
        } else {
            // if we haven't, add them to the validation mapping
            validation[dest].seen = true;
            validation[dest].received = wad; 
            seen.push(dest);   
        }
    }

    /// @dev performs the validation for an attempted transitive transfer
    /// @param steps the number of steps in the transitive transaction
    function validateTransferThrough(uint256 steps) internal {
        // a valid path has only one real sender and receiver
        address src;
        address dest;
        // iterate through the array of all the addresses that were part of the transaction data
        for (uint i = 0; i < seen.length; i++) {
            transferValidator memory curr = validation[seen[i]];
            // if the address sent more than they received, they are the sender
            if (curr.sent > curr.received) {
                // if we've already found a sender, transaction is invalid
                require(src == address(0), "Path sends from more than one src");
                // the real token sender must also be the transaction sender
                require(seen[i] == msg.sender, "Path doesn't send from transaction sender");
                src = seen[i];
            }
            // if the address received more than they sent, they are the recipient
            if (curr.received > curr.sent) {
                // if we've already found a recipient, transaction is invalid
                require(dest == address(0), "Path sends to more than one dest");
                dest = seen[i];
            }
        }
        // a valid path has both a sender and a recipient
        require(src != address(0), "Transaction must have a src");
        require(dest != address(0), "Transaction must have a dest");
        // sender should not recieve, recipient should not send
        // by this point in the code, we should have one src and one dest and no one else's balance should change
        require(validation[src].received == 0, "Sender is receiving");
        require(validation[dest].sent == 0, "Recipient is sending");
        // the total amounts sent and received by sender and recipient should match
        require(validation[src].sent == validation[dest].received, "Unequal sent and received amounts");
        // the maximum amount of addresses we should see is one more than steps in the path
        require(seen.length <= steps + 1, "Seen too many addresses");
        emit HubTransfer(src, dest, validation[src].sent);
        // clean up the validation datastructures
        for (uint i = seen.length; i >= 1; i--) {
            delete validation[seen[i-1]];
        }
        delete seen;
        // sanity check that we cleaned everything up correctly
        require(seen.length == 0, "Seen should be empty");
    }

    /// @notice walks through tokenOwners, srcs, dests, and amounts array and executes transtive transfer
    /// @dev tokenOwners[0], srcs[0], dests[0], and wads[0] constitute a transaction step
    /// @param tokenOwners the owner of the tokens being sent in each transaction step
    /// @param srcs the sender of each transaction step
    /// @param dests the recipient of each transaction step
    /// @param wads the amount for each transaction step
    function transferThrough(
        address[] memory tokenOwners,
        address[] memory srcs,
        address[] memory dests,
        uint[] memory wads
    ) public {
        // all the arrays must be the same length
        require(dests.length == tokenOwners.length, "Tokens array length must equal dests array");
        require(srcs.length == tokenOwners.length, "Tokens array length must equal srcs array");
        require(wads.length == tokenOwners.length, "Tokens array length must equal amounts array");
        for (uint i = 0; i < srcs.length; i++) {
            address src = srcs[i];
            address dest = dests[i];
            address token = tokenOwners[i];
            uint256 wad = wads[i];
            
            // check that no trust limits are violated
            uint256 max = checkSendLimit(token, src, dest);
            require(wad <= max, "Trust limit exceeded");

            buildValidationData(src, dest, wad);
            
            // go ahead and do the transfers now so that we don't have to walk through this array again
            userToToken[token].hubTransfer(src, dest, wad);
        }
        // this will revert if there are any problems found
        validateTransferThrough(srcs.length);
    }
}