Skip to content

Commit

Permalink
Merge pull request #4 from violetprotocol/dev
Browse files Browse the repository at this point in the history
v0.1.1-rc1
  • Loading branch information
0xpApaSmURf authored Apr 28, 2022
2 parents 258f9d5 + 8e81c21 commit 8fd71db
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 21 deletions.
4 changes: 2 additions & 2 deletions contracts/AuthCompatible.sol
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ contract AuthCompatible {
let endOfSigExp := add(startPos, 0x80)
let totalInputSize := sub(calldatasize(), endOfSigExp)

// disgusting dirty putrid abomination of a detestable drivelous hack
// because for some reason byte array pointers are being assigned the same address as another causing overwrite
// disgusting dirty putrid abomination of a detestable drivelous hack because
// for some reason byte array pointers are being assigned the same address as another causing overwrite
inputs := add(inputs, mul(calldatasize(), 2))

// Store expected length of total byte array as first value
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
{
"name": "@violetprotocol/ethereum-access-token",
"description": "Smart contracts for on-chain token-based access",
"version": "0.1.0",
"version": "0.1.1",
"author": {
"name": "papasmurf"
},
"files": [
"contracts"
],
"devDependencies": {
"@codechecks/client": "^0.1.12",
"@commitlint/cli": "^16.2.1",
Expand Down Expand Up @@ -54,9 +57,6 @@
"typechain": "^7.0.0",
"typescript": "^4.6.2"
},
"files": [
"/contracts"
],
"keywords": [
"blockchain",
"ethereum",
Expand All @@ -77,7 +77,7 @@
"lint:sol": "solhint --config ./.solhint.json --max-warnings 0 \"contracts/**/*.sol\"",
"lint:ts": "eslint --config ./.eslintrc.yaml --ignore-path ./.eslintignore --ext .js,.ts .",
"prepare": "yarn clean && env COMPILE_MODE=production yarn compile && yarn typechain",
"postinstall": "husky install",
"_postinstall": "husky install",
"postpublish": "pinst --enable",
"prepublishOnly": "pinst --disable",
"prettier": "prettier --config ./.prettierrc.yaml --write \"**/*.{js,json,md,sol,ts}\"",
Expand Down
75 changes: 75 additions & 0 deletions src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Ethereum Access Token Helpers

Utilities for the Ethereum Access Token smart contract system.

Use these tools to help you generate and sign your EATs. First ensure that your smart contracts follow appropriate EAT interfaces by ensuring all functions that intend to be modified with `requiresAuth` to use the following parameters prepended before your usual function parameters:

```solidity
function yourFunction(uint8 v, bytes32 r, bytes32 s, uint256 expiry, ...) {}
```

where you insert your own function parameters in place of `...`.

## Install

Using npm:
`npm install @violetprotocol/ethereum-access-token-helpers`

Using yarn:
`yarn add @violetprotocol/ethereum-access-token-helpers`

## Usage

```typescript
const { splitSignature } = require("@ethersproject/bytes");
const {
signAuthMessage,
getSignerFromMnemonic, getSignerFromPrivateKey
packParameters
} = require("@violetprotocol/ethereum-access-token-helpers/utils");

const INTERVAL: number = 100 // seconds
const FUNCTION_SIGNATURE = "0xabcdefgh";
const CONTRACT: ethers.Contract = ...; // for example an ERC20 token contract
const SIGNER: ethers.Signer = ...;
const CALLER: ethers.Signer = ...;
const VERIFIER = "0x..."; // AuthVerifier contract address

const recipient = "0x123...";
const amount = 1;

// AuthToken domain for clear namespacing
const authDomain = {
name: "Ethereum Access Token",
version: "1",
chainId: SIGNER.getChainId(),
verifyingContract: VERIFIER,
};

// Construct AuthToken message with relevant data using ERC20 `transfer(address to, uint256 amount)` as the example tx
// In the Auth compatible case, the ERC20 transfer function actually looks like this:
// `transfer(uint8 v, bytes32 r, bytes32 s, uint256 expiry, address to, uint256 amount)`
// where we just augment the original function with the required parameters for auth
// the `parameters` property takes a packed, abi-encoded set of original function parameters
const authMessage = {
expiry: Math.floor(new Date().getTime() / 1000) + interval,
functionCall: {
functionSignature: FUNCTION_SIGNATURE,
target: CONTRACT.address.toLowerCase(),
caller: CALLER.address.toLowerCase(),
parameters: packParameters(CONTRACT.interface, "transfer", [recipient, amount]),
},
};

// Sign the AuthToken using the Signer
const signature = splitSignature(await signAuthMessage(SIGNER, authDomain, authMessage));

// Pass all signed data to a transaction function call
await CONTRACT.functionName(
signature.v,
signature.r,
signature.s,
authMessage.expiry,
...params
)
```
4 changes: 2 additions & 2 deletions src/package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "@violetprotocol/ethereum-access-token-helpers",
"description": "Typescript bindings and utilities for Ethereum Access Token",
"version": "0.1.0",
"version": "0.1.1",
"main": "dist/index.js",
"files": [
"dist"
"dist/*"
],
"scripts": {
"prepare": "bash ../scripts/prepare-artifacts.sh && tsc"
Expand Down
9 changes: 0 additions & 9 deletions src/utils/dummy.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export { signAuthMessage } from "./signAuthMessage";
export { signMailMessage } from "./signMailMessage";
export { getSignerFromMnemonic, getSignerFromPrivateKey } from "./signer";
export { packParameters as packDummyParameters } from "./dummy";
export { packParameters } from "./packParameters";
28 changes: 28 additions & 0 deletions src/utils/packParameters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { hexlify } from "@ethersproject/bytes";
import { ethers } from "ethers";

const packParameters = (
contractInterface: ethers.utils.Interface,
functionNameOrSelector: string,
params: any[],
): string => {
// detect function fragment
const functionFragment = contractInterface.getFunction(functionNameOrSelector);

// check if selected function fragment complies with auth compatible function format:
// functionName(uint8 v, bytes32 r, bytes32 s, uint256 expiry, ...)
if (!isAuthCompatible(functionFragment)) throw "packParameters: specified function is not AuthCompatible";

// hexlify function encoding from index 4 onwards with parameters
return hexlify(contractInterface._encodeParams(functionFragment.inputs.slice(4), params));
};

const isAuthCompatible = (functionFragment: ethers.utils.FunctionFragment): boolean => {
if (functionFragment.inputs[0].name != "v" || functionFragment.inputs[0].type != "uint8") return false;
if (functionFragment.inputs[1].name != "r" || functionFragment.inputs[1].type != "bytes32") return false;
if (functionFragment.inputs[2].name != "s" || functionFragment.inputs[2].type != "bytes32") return false;
if (functionFragment.inputs[3].name != "expiry" || functionFragment.inputs[3].type != "uint256") return false;
return true;
};

export { packParameters };
4 changes: 2 additions & 2 deletions test/authCompatible.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { AuthVerifier } from "../src/types/AuthVerifier";
import { AuthTokenStruct } from "../src/types/IAuthVerifier";
import { DummyDapp } from "../src/types/DummyDapp";
import { signAuthMessage } from "../src/utils/signAuthMessage";
import { packParameters as packDummyParameters } from "../src/utils/dummy";
import { packParameters } from "../src/utils/packParameters";
import { splitSignature } from "@ethersproject/bytes";

const chai = require("chai");
Expand Down Expand Up @@ -55,7 +55,7 @@ describe("AuthCompatible", function () {
target: this.dapp.address.toLowerCase(),
caller: this.signers.admin.address.toLowerCase(),
// Parameters are hexadecimally represented, left-padded with 0 to multiples of 64-characters (32-bytes), and concatenated together
parameters: packDummyParameters(this.testTokenAddress, this.amount),
parameters: packParameters(this.dapp.interface, "lend", [this.testTokenAddress, this.amount]),
},
};
});
Expand Down

0 comments on commit 8fd71db

Please sign in to comment.