base contracts

This commit is contained in:
Mason 2022-11-15 12:27:17 -06:00
parent 68ff6a064e
commit c56b044c7e
10 changed files with 10487 additions and 2 deletions

1
apps/.gitignore vendored
View File

@ -3,3 +3,4 @@
.RData
.Ruserdata
.DS_Store
secrets.txt

View File

@ -0,0 +1,2 @@
node_modules/
.env

View File

@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
contract AttestationStation {
mapping(address => mapping(address => mapping(bytes32 => bytes))) public attestations;
struct AttestationData {
address about;
bytes32 key;
bytes val;
}
event AttestationCreated(
address indexed creator,
address indexed about,
bytes32 indexed key,
bytes val
);
function attest(AttestationData[] memory _attestations) public {
for (uint256 i = 0; i < _attestations.length; ++i) {
AttestationData memory attestation = _attestations[i];
attestations[msg.sender][attestation.about][attestation.key] = attestation.val;
emit AttestationCreated(
msg.sender,
attestation.about,
attestation.key,
attestation.val
);
}
}
}

View File

@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface IAttestationStation {
struct AttestationData {
address about;
bytes32 key;
bytes val;
}
event AttestationCreated(
address indexed creator,
address indexed about,
bytes32 indexed key,
bytes val
);
function attest(AttestationData[] memory _attestations)
external;
}

View File

@ -0,0 +1,112 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import { IAttestationStation } from "./AttestationStation/IAttestationStation.sol";
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
contract FlipsideAttestation {
using ECDSA for bytes32;
/// @dev The address used to sign attestations and manage the contract.
address public signer;
/// @dev The interface for OP's Attestation Station.
IAttestationStation public attestationStation;
constructor(
address _signer
, address _attestationStation
) {
signer = _signer;
attestationStation = IAttestationStation(_attestationStation);
}
/**
* @notice Allows the signer to change the AttestationStation implementation.
* @param _attestationStation The address of the new AttestationStation implementation.
*
* Requirements:
* - The caller must be the current signer.
*/
function setAttestationStation(address _attestationStation) public {
require(msg.sender == signer, "FlipsideAttestation: Only signer can set OP AttestationStation");
attestationStation = IAttestationStation(_attestationStation);
}
/**
* @notice Allows the signer to transfer signer privilege to another address.
* @param _signer The address of the new signer.
*
* Requirements:
* - The caller must be the current signer.
*/
function setSigner(address _signer) public {
require(msg.sender == signer, "FlipsideAttestation: Only signer can change signer");
signer = _signer;
}
/**
* @notice Verifies the attestation data before calling the OP AttestationStation attest.
* @param _about The address of the account to be attested.
* @param _key The key of the attestation.
* @param _val The value of the attestation.
* @param _signature The signature of the attestation.
*
* Requirements:
* - The caller must be the current signer.
*/
function attest(
address _about
, bytes32 _key
, bytes memory _val
, bytes memory _signature
)
public
{
_verifySignature(
_about
, _key
, _val
, _signature
);
// Send the attestation to the Attestation Station.
IAttestationStation.AttestationData[] memory attestations = new IAttestationStation.AttestationData[](1);
attestations[0] = IAttestationStation.AttestationData({
about: _about
, key: _key
, val: _val
});
attestationStation.attest(attestations);
}
/**
* @notice Allows the signer to change the AttestationStation implementation.
* @param _about The address of the account to be attested.
* @param _key The key of the attestation.
* @param _val The value of the attestation.
* @param _signature The signer's signed message of the attestation.
*
* Requirements:
* - The signature must resolve to the signer.
*/
function _verifySignature(
address _about
, bytes32 _key
, bytes memory _val
, bytes memory _signature
)
internal
view
{
bytes32 messageHash = keccak256(
abi.encodePacked(
_about
, _key
, _val
)
);
require(messageHash.toEthSignedHash().recover(_signature) == signer, "FlipsideAttestation: Invalid signature");
}
}

View File

@ -0,0 +1,4 @@
OPTIMISM_EXPLORER_API_KEY=""
COINMARKETCAP_API_KEY=""
ALCHEMY_API_KEY=""
PRIVATE_KEY=""

View File

@ -0,0 +1,132 @@
require("hardhat-gas-reporter");
require('hardhat-deploy');
require("hardhat-watcher");
require("hardhat-tracer");
require("hardhat-abi-exporter");
require("hardhat-api-builder");
require("hardhat-docgen");
require("@nomiclabs/hardhat-waffle");
require("@nomiclabs/hardhat-etherscan");
require('solidity-coverage');
require("dotenv").config();
task("deploy", "Deploys the protocol")
.addFlag("verify", "Verify the deployed contracts on Etherscan")
.addParam("signerAddress", "The address of the account that will sign the attestations")
.addParam("attestationImplementation", "The address of the attestation implementation contract")
.setAction(async (taskArgs, hre) => {
// Compiling all of the contracts again just in case
await hre.run('compile');
const [deployer] = await ethers.getSigners();
console.log(`✅ Connected to ${deployer.address}`);
const chainId = await getChainId()
let attestationImplementation = taskArgs.attestationImplementation;
// Deploy a mock attestation implementation if none is provided
if (attestationImplementation === undefined) {
const AttestationStation = await hre.ethers.getContractFactory("Attestation");
opAtt = await AttestationStation.deploy();
opAtt = await AttStat.deployed();
attestationImplementation = attestationImplementationContractDeployed.address;
console.log("✅ Mock Attestation Station Deployed.");
}
// Deploying the FlipsideAttestation router
const FlipsideAttestation = await ethers.getContractFactory("FlipsideAttestation");
flipAtt = await FlipsideAttestation.deploy(
taskArgs.signerAddress,
attestationImplementation,
);
flipAtt = await flipAtt.deployed();
console.log("✅ Flipside Attestation Deployed.");
flipAttDeployment = {
"Chain ID": chainId,
"Deployer": deployer.address,
"Flipside Attestation Address": flipAtt.address,
"Remaining ETH Balance": parseInt((await deployer.getBalance()).toString()) / 1000000000000000000,
}
console.table(flipAttDeployment)
// Verifying
if (taskArgs.verify !== false && chainId != '31337') {
// Give time for etherscan to confirm the contract before verifying.
await new Promise(r => setTimeout(r, 30000));
await hre.run("verify:verify", {
address: flipAtt.address,
constructorArguments: [
taskArgs.signerAddress,
attestationImplementation
],
});
console.log("✅ Flipside Attestation Verified.")
}
});
module.exports = {
solidity: {
compilers: [
{
version: "0.8.17",
settings: {
optimizer: { // Keeps the amount of gas used in check
enabled: true,
runs: 1000
}
}
}
],
},
gasReporter: {
currency: 'USD',
gasPrice: 20,
coinmarketcap: process.env.COINMARKETCAP_API_KEY,
showMethodSig: true,
showTimeSpent: true,
},
watcher: {
compilation: {
tasks: ["compile"],
files: ["./contracts"],
verbose: true,
},
ci: {
tasks: ["clean", { command: "compile", params: { quiet: true } }, { command: "test", params: { noCompile: true, testFiles: ["testfile.ts"] } }],
}
},
abiExporter: {
path: 'abis/',
runOnCompile: true,
clear: true,
flat: true,
spacing: 2,
format: "minimal"
},
etherscan: {
apiKey: {
optimism: process.env.OPTIMISM_EXPLORER_API_KEY,
}
},
defaultNetwork: "hardhat",
networks: {
hardhat: {
chainId: 1337,
gas: "auto",
gasPrice: "auto",
saveDeployments: false,
mining: {
auto: false,
order: 'fifo',
interval: 1500,
}
},
optimism: {
url: `https://eth-goerli.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`,
accounts: [`0x${process.env.PRIVATE_KEY}`],
gasPrice: 5000000000, // 5 gwei
},
}
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
{
"name": "attestation_contracts",
"version": "1.0.0",
"description": "Contracts for OP attestation station",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "@masonchain",
"license": "MIT",
"devDependencies": {
"ethers": "^5.7.2",
"hardhat": "^2.12.2"
},
"dependencies": {
"@openzeppelin/contracts": "^4.8.0",
"hardhat-gas-reporter": "^1.0.9"
}
}

View File

@ -3,5 +3,4 @@ library(shinyBS)
library(data.table)
load("data.RData")
signer_private_key <- readLines("secrets.txt")