-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9c8bf9d
commit 3744afc
Showing
9 changed files
with
4,134 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {FunctionsClient} from "@chainlink/contracts/src/v0.8/functions/v1_0_0/FunctionsClient.sol"; | ||
import {ConfirmedOwner} from "@chainlink/contracts/src/v0.8/shared/access/ConfirmedOwner.sol"; | ||
import {FunctionsRequest} from "@chainlink/contracts/src/v0.8/functions/v1_0_0/libraries/FunctionsRequest.sol"; | ||
import "@openzeppelin/contracts/utils/Strings.sol"; | ||
|
||
contract SafeCity is FunctionsClient, ConfirmedOwner { | ||
using FunctionsRequest for FunctionsRequest.Request; | ||
|
||
error UnexpectedRequestID(bytes32 requestId); | ||
|
||
string source = | ||
"const contractAddress = args[0];" | ||
"const userAddress = args[1];" | ||
"const currentBlock = args[2];" | ||
"const startBlock = currentBlock - 1800;" | ||
"const url = `https://explorer.linea.build/api?module=account&action=txlist&address=${contractAddress}&startblock=${startBlock}&endblock=${currentBlock}&sort=desc&offset=100&page=0&filterBy=to`" | ||
"const apiRequest = Functions.makeHttpRequest({" | ||
"url: url" | ||
"});" | ||
"const apiResponse = await apiRequest;" | ||
"if (apiResponse.error) {" | ||
"throw Error('Request failed');" | ||
"}" | ||
"const data = apiResponse.data;" | ||
"const result = data.result.some(entity => entity.from === userAddress);" | ||
"return Functions.encodeUint256(result == true ? 1 : 0);"; | ||
|
||
//Callback gas limit | ||
uint32 gasLimit = 300000; | ||
|
||
bytes32 donID; | ||
uint64 subscriptionID; | ||
|
||
struct Review { | ||
address reviewer; | ||
bool happy; | ||
string review; | ||
} | ||
|
||
// Review[] public reviews; | ||
mapping(address reviewedAddress => Review[]) private reviews; | ||
|
||
struct FunctionRequestMetadata { | ||
address reviewer; | ||
address reviewedAddress; | ||
bool happy; | ||
string review; | ||
} | ||
|
||
mapping(bytes32 => FunctionRequestMetadata) private functionRequestMetadata; | ||
|
||
event NewReview(address reviewedAddress, address reviewer, bool happy, string review, bytes error); | ||
|
||
/** | ||
* @notice Initializes the contract with the Chainlink router address and sets the contract owner | ||
*/ | ||
constructor( | ||
address router, | ||
bytes32 _donID, | ||
uint64 _subscriptionID | ||
) FunctionsClient(router) ConfirmedOwner(msg.sender) { | ||
donID = _donID; | ||
subscriptionID = _subscriptionID; | ||
} | ||
|
||
function reportHappiness(address _reviewedAddress, bool happy, string memory review) public { | ||
FunctionsRequest.Request memory req; | ||
req.initializeRequestForInlineJavaScript(source); | ||
string[] memory args = new string[](3); | ||
args[0] = toAsciiString(_reviewedAddress); | ||
args[1] = toAsciiString(msg.sender); | ||
args[2] = Strings.toString(block.number); | ||
req.setArgs(args); | ||
|
||
// Send the request and store the request ID | ||
bytes32 requestId = _sendRequest( | ||
req.encodeCBOR(), | ||
subscriptionID, | ||
gasLimit, | ||
donID | ||
); | ||
|
||
functionRequestMetadata[requestId] = FunctionRequestMetadata( | ||
msg.sender, | ||
_reviewedAddress, | ||
happy, | ||
review | ||
); | ||
} | ||
|
||
function getRecentReviews(address _reviewedAddress) public view returns (Review[] memory) { | ||
return reviews[_reviewedAddress]; | ||
} | ||
|
||
function toAsciiString(address x) internal pure returns (string memory) { | ||
bytes memory s = new bytes(40); | ||
for (uint i = 0; i < 20; i++) { | ||
bytes1 b = bytes1(uint8(uint(uint160(x)) / (2**(8*(19 - i))))); | ||
bytes1 hi = bytes1(uint8(b) / 16); | ||
bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); | ||
s[2*i] = char(hi); | ||
s[2*i+1] = char(lo); | ||
} | ||
return string(s); | ||
} | ||
|
||
function char(bytes1 b) internal pure returns (bytes1 c) { | ||
if (uint8(b) < 10) return bytes1(uint8(b) + 0x30); | ||
else return bytes1(uint8(b) + 0x57); | ||
} | ||
|
||
/** | ||
* @notice Callback function for fulfilling a request | ||
* @param requestId The ID of the request to fulfill | ||
* @param response The HTTP response data | ||
* @param err Any errors from the Functions request | ||
*/ | ||
function fulfillRequest( | ||
bytes32 requestId, | ||
bytes memory response, | ||
bytes memory err | ||
) internal override { | ||
if (bytes(functionRequestMetadata[requestId].review).length == 0) { | ||
revert UnexpectedRequestID(requestId); | ||
} | ||
|
||
address _reviewer = functionRequestMetadata[requestId].reviewer; | ||
address _reviewedAddress = functionRequestMetadata[requestId].reviewedAddress; | ||
bool _happy = functionRequestMetadata[requestId].happy; | ||
string memory _review = functionRequestMetadata[requestId].review; | ||
|
||
if (abi.decode(response, (uint256)) == 1) { | ||
Review memory newReview = Review(_reviewer, _happy, _review); | ||
reviews[_reviewedAddress].push(newReview); | ||
} | ||
|
||
emit NewReview(_reviewedAddress, _reviewer, _happy, _review, err); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
require('@nomicfoundation/hardhat-toolbox'); | ||
require('dotenv').config() | ||
|
||
module.exports = { | ||
solidity: { | ||
Check failure on line 5 in packages/backend/hardhat.config.js GitHub Actions / Build, lint, and test / Lint
|
||
version: "0.8.24", | ||
Check failure on line 6 in packages/backend/hardhat.config.js GitHub Actions / Build, lint, and test / Lint
|
||
settings: { | ||
Check failure on line 7 in packages/backend/hardhat.config.js GitHub Actions / Build, lint, and test / Lint
|
||
optimizer: { | ||
Check failure on line 8 in packages/backend/hardhat.config.js GitHub Actions / Build, lint, and test / Lint
|
||
enabled: true | ||
} | ||
} | ||
}, | ||
allowUnlimitedContractSize: true, | ||
networks: { | ||
hardhat: {}, | ||
ETH_SEPOLIA: { | ||
accounts: [`${process.env.PRIVATE_KEY}`], | ||
url: `https://eth-sepolia.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}` | ||
}, | ||
}, | ||
etherscan: { | ||
apiKey: `${process.env.ETHERSCAN_API_KEY}` | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"name": "safe-city-contracts", | ||
"version": "0.1.0", | ||
"private": true, | ||
"scripts": { | ||
"build": "npx hardhat compile", | ||
"deploy-sepolia": "npx hardhat run ./scripts/deploy.js --network ETH_SEPOLIA", | ||
"deploy-linea-sepolia": "npx hardhat run ./scripts/deploy.js --network LINEA_SEPOLIA", | ||
"node": "npx hardhat node", | ||
"deploy-local": "npx hardhat run ./scripts/deploy.js --network localhost" | ||
}, | ||
"devDependencies": { | ||
"@chainlink/contracts": "^1.1.1", | ||
"@nomicfoundation/hardhat-chai-matchers": "^2.0.4", | ||
"@nomicfoundation/hardhat-ethers": "^3.0.0", | ||
"@nomicfoundation/hardhat-network-helpers": "^1.0.0", | ||
"@nomicfoundation/hardhat-toolbox": "^4.0.0", | ||
"@nomicfoundation/hardhat-verify": "^2.0.0", | ||
"@openzeppelin/contracts": "^5.0.1", | ||
"@typechain/ethers-v6": "^0.5.0", | ||
"@typechain/hardhat": "^9.0.0", | ||
"@types/chai": "^4.2.0", | ||
"@types/mocha": ">=9.1.0", | ||
"chai": "^4.2.0", | ||
"dotenv": "^16.0.2", | ||
"ethers": "^6.10.0", | ||
"hardhat": "latest", | ||
"hardhat-gas-reporter": "^1.0.8", | ||
"solidity-coverage": "^0.8.1", | ||
"ts-node": ">=8.0.0", | ||
"typechain": "^8.3.0", | ||
"typescript": ">=4.5.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
const { ethers } = require('hardhat'); | ||
|
||
async function main() { | ||
const DomainOwnership = await ethers.getContractFactory('SafeCity'); | ||
const domainOwnership = await DomainOwnership.deploy( | ||
// Sepolia | ||
"0xb83E47C2bC239B3bf370bc41e1459A34b41238D0", // router address - Check to get the router address for your supported network https://docs.chain.link/chainlink-functions/supported-networks | ||
"0x66756e2d657468657265756d2d7365706f6c69612d3100000000000000000000", // donID - Check to get the donID for your supported network https://docs.chain.link/chainlink-functions/supported-networks | ||
3107 // subscription ID | ||
); | ||
await domainOwnership.waitForDeployment(); | ||
|
||
console.log("DomainOwnership deployed to:", await domainOwnership.getAddress()); | ||
} | ||
|
||
main() | ||
.then(() => process.exit(0)) | ||
.catch((error) => { | ||
console.error(error); | ||
process.exit(1); | ||
}); |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.