# Token Subscription (MetaTx) Community Audit
This audit was performed upon the commit [9ff9deb](https://github.com/austintgriffith/tokensubscription.com/tree/9ff9deb10430aacb5bce44a34e16a9c446fb3f4d) by Dean Eigenmann, it was done as part of the [ZK Labs community audit initiative](https://blog.zklabs.io/zk-labs-community-audits-initiative-for-non-ico-projects-ea7830d082f8
).
The code is kept simple & concise, there is no unnecessary complexity found in the smart contract.
**Mentioned issue fixes and suggestions were implemented as of commit [13ced40](https://github.com/austintgriffith/tokensubscription.com/tree/13ced407c2709e99fbe7838a84a9d53f855b40bc).**
## Contract Intent
The Token Subscription (MetaTx) project enables applications to create a trustless subscription model without their users needing to constantly and manually transfer tokens. It consists of one contract, the Subscription contract, which is created with the parameters for a subscription including destination address, token address, token amount, and period of recurrence. The publisher then supplies a link to the subscriber that is presented with the terms of the subscription to sign an off-chain meta transaction that is replayed on the defined period. The subscriber controls the flow of the tokens (starting, stopping, pausing, etc) using the ERC20 standard ```approve()``` function.
More information can be found through the [website](https://tokensubscription.com/).
## Tests
There does not seem to be any tests covering the smart contracts, these types of tests should be created.
## Subscription.sol
- ```ECDSA``` is used for all ```bytes32``` variables.
- ```SafeMath``` is used for all ```uint256``` variables.
### Suggestions
- Move mapping on ```L72``` to there where rest of the variables are defined.
- Move ```constructor``` to the rest of the function definitions.
- Stick to a consistent code style.
- Make all functions that need not be called by the contract itself ```external```.
- Add a ```nonce``` field to subscription signatures. Making it possible to reopen cancelled subscriptions.
### Constructor
This function sets various fields:
- requiredToAddress
- requiredTokenAddress
- requiredTokenAmount
- requiredPeriodSeconds
- requiredGasPrice
- author
### isSubscriptionActive
This function returns whether the ```nextValidTimestamp``` for a given subscription with a ```gracePeriod``` added to it is smaller than or equal to the current ```timestamp```.
### getSubscriptionHash
This function packs the passed variables using the ```abi.encodePacked``` function and then proceeds to hashing those bytes using the ```keccak256``` function.
### getSubscriptionSigner
This function recovers the signer of a given message using the ```recover``` function found in the ```ECDSA``` library.
### isSubscriptionReady
This function checks multiple things, such as:
- That the signer of the message is equal to the ```from``` address.
- That the ```from``` address is not equal to the ```to``` address.
- That the current time is greater than or equal to the ```nextValidTimestamp``` for the given subscription.
- Ensures that the token allowance is greater than the ```tokenAmount``` added with the ```gasPrice```.
- Ensures that the token balance is greater than the ```tokenAmount``` added with the ```gasPrice```.
### cancelSubscription
First the subscription hash is generated by the passed variables using the ```getSubscriptionHash``` function. The ```signer``` is then recovered using the ```recover``` function found in the ```ECDSA``` library. It is then ensured that the ```signer``` is equal to the value of the passed ```from``` variable. Finally the ```nextValidTimestamp``` for the given subscription is set to ```2**256 - 1```.
#### Suggestions
- Instead of doing the whole ```recover``` call, the ```getSubscriptionSigner``` function can be called as it has been in other functions.
### executeSubscription
Initially the subscription hash is generated using the ```getSubscriptionHash``` function. Then the signer is recovered using the ```getSubscriptionSigner``` function. Next it is ensured that the ```signer``` is equal to the passed ```from``` address. It is then ensured that the current timestamp is greater than or equal to the value of the ```nextValidTimestamp``` for the given subscription.
Several checks are then run:
- It is ensured that the ```requiredToAddress``` is either equal to ```0x0``` or the passed ```to``` variable.
- It is ensured that the ```requiredTokenAddress``` is either equal to ```0x0``` or the passed ```tokenAddress``` variable.
- It is ensured that the ```requiredTokenAmount``` is either equal to ```0``` or the passed ```tokenAmount``` variable.
- It is ensured that the ```requiredPeriodSeconds``` is either equal to ```0``` or the passed ```periodSeconds``` variable.
- It is ensured that the ```requiredGasPrice``` is either equal to ```0``` or the passed ```gasPrice``` variable.
The value of the ```nextValidTimestamp``` for the given subscription is then set to the current timestamp added to the ```periodSeconds``` variable.
Tokens are then transfered from the ```from``` address to the passed ```to``` address using the ```transferFrom``` function. It is ensured that tokens were transfered successfully by adding the balance of the ```to``` address before the transfer to the transfered amount and ensuring that said value is equal to the new balance of the ```to``` address. The ```ExecuteSubscription``` event is then emitted.
Finally is the value of ```gasPrice``` is greater than zero, the value is transfered to the function caller from the ```from``` address.
#### Issues
- The ```require``` on ```L233-236``` will not work for every token. See [here](https://medium.com/@chris_77367/explaining-unexpected-reverts-starting-with-solidity-0-4-22-3ada6e82308c).
- Should this function not call ```isSubscriptionReady```?