5

I am coding up a PoC for a free market basic income mechanism, and am trying to figure out how to get the historical balance of msg.sender, as well as the time since that address was generated.

Historical balance: There is no 'total received' variable for an address, right? Should this then be calculated by the contract, or would it be far more gas effective to have this done by a javascript app, or use a block explorer?

Life span of address: how do I retrieve the block number of msg.sender's first transaction and then calculate the rough time in days or months since that occurred?

I am fairly new to Solidity and haven't had too much programming experience.

5

Those data are unavailable as they would require access to the entire past intermediate state of the blockchain. A contract can only access the current state.

If you want to do this for very specific contract addresses, you might extend them to maintain some historical data that you might be interested in, but this would be doable only for contracts that you control (or that you supply the code for). You won't be able to access such data on chain from within Solidity.

  • Is it possible to check the balance of a specified address in solidity? For example a contract that makes a donation if a particular address hasn't received anything for X days. – Philip Kirkbride Mar 20 '16 at 5:24
2

You could keep a map of (blockchain_number + address) -> balance in your contract, and update it every time you need to interact with that address. This will use up a large amount of storage and cost you lots of gas. (e.g. on the order of $0.005 USD per interaction with that address). I wouldn't recommend this.

What I'm doing in my contract is keeping counters or magnitudes for each address of interest. This fulfills the total received requirement. Gas is very cheap for an update. For example in solidity:

// consider this pseudo-code, I didn't run the compiler...
struct User {
    bool isValid;
    uint netEtherReceived;  // a counter, it always goes up
    uint netEtherSent;      // a counter, it always goes up
    uint currentBalance;    // a magnitude, what we are holding in this contract for this user.  Goes up and down.
    // other stuff of interest for that user
}
mapping (address => User) users

function receiveEther() {
    if (users[msg.sender].isValid == true) {
        users[msg.sender].netEtherReceived += msg.value;
        users[msg.sender].currentBalance += msg.value;
    }
}
// not shown - subtract from the balance when you address.send().

This is trust minimized - you can always be confident that the counters are correct, unlike keeping stuff off the blockchain.

I also issue events for any important state change e.g. msg.value and use web3.js, and bunyan to log those events to redundant off blockchain storage in machine readable format. The events are kept off chain and thus aren't trust minimized, but I (will) keep them checksummed and redundant and use them for analytics and auditing (not to mention really useful for debugging and automated testing).

As far as your Lifespan requirement I thought there was a historical blockchain state service out there, but I don't know what it is. Someone else will have to answer that. I kind of need to know that too.

[EDIT] - see etherscan.io for a service that allows you to check blocks and transactions. It looks like it has history back to the genesis block. It's not trust minimized, but hopefully there will be multiple services like this at some point.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.