Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feat/oauth-mvp' into feat/oauth-…
Browse files Browse the repository at this point in the history
…mvp-test
  • Loading branch information
wshino committed Sep 26, 2024
2 parents 7e2e6a3 + ce7b670 commit d118f14
Show file tree
Hide file tree
Showing 47 changed files with 5,273 additions and 2,061 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,7 @@ book

# Vs code settings
.vscode

# Oauth-sdk
packages/oauth-sdk/.env
packages/oauth-sdk/dist
2 changes: 1 addition & 1 deletion Relayer.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Use the base image
FROM bisht13/relayer-base:latest
FROM sorasue/relayer-base:latest

# Copy the project files
COPY packages/relayer /relayer/packages/relayer
Expand Down
82 changes: 80 additions & 2 deletions packages/contracts/script/DefaultSetupScript.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ contract Deploy is Script {

ECDSAOwnedDKIMRegistry dkim;

OauthCore oauthCoreImpl;
OauthCore oauthCore;

Wallet walletImpl;
Expand Down Expand Up @@ -86,7 +87,7 @@ contract Deploy is Script {
string[][] nftExtTemplates = new string[][](3);
string[][] uniswapExtTemplates = new string[][](4);
string[][] safeExtTemplates = new string[][](1);
string[][] oauthUpExtTemplates = new string[][](1);
string[][] oauthUpExtTemplates = new string[][](9);
string[][] oauthInExtTemplates = new string[][](8);

function run() external {
Expand Down Expand Up @@ -139,7 +140,12 @@ contract Deploy is Script {

dkim = new ECDSAOwnedDKIMRegistry(signer);

oauthCore = new OauthCore();
{
oauthCoreImpl = new OauthCore();
bytes memory data = abi.encodeWithSelector(OauthCore(oauthCoreImpl).initialize.selector);
ERC1967Proxy proxy = new ERC1967Proxy(address(oauthCoreImpl), data);
oauthCore = OauthCore(payable(address(proxy)));
}

walletImpl = new Wallet(address(weth), address(oauthCore));

Expand Down Expand Up @@ -298,6 +304,77 @@ contract Deploy is Script {
oauthUpExt = OauthSignupExtension(payable(address(proxy)));
}
oauthUpExtTemplates[0] = ["Sign-up", "{string}"];
// (0,0) = 0
oauthUpExtTemplates[1] = ["Sign-up", "{string}", "on", "device", "{uint}"];
// (0,1) = 1
oauthUpExtTemplates[2] = ["Sign-up", "{string}", "on", "device", "{uint}", "for", "{tokenAmount}"];
// (0,2) = 2
oauthUpExtTemplates[3] = [
"Sign-up",
"{string}",
"on",
"device",
"{uint}",
"for",
"{tokenAmount}",
"{tokenAmount}"
];
// (0,3) = 3
oauthUpExtTemplates[4] = [
"Sign-up",
"{string}",
"on",
"device",
"{uint}",
"for",
"{tokenAmount}",
"{tokenAmount}",
"{tokenAmount}"
];
// (1,0) = 4
oauthUpExtTemplates[5] = ["Sign-up", "{string}", "on", "device", "{uint}", "until", "timestamp", "{uint}"];
// (1,1) = 4 + 1 = 5
oauthUpExtTemplates[6] = [
"Sign-up",
"{string}",
"on",
"device",
"{uint}",
"until",
"timestamp",
"{uint}",
"for",
"{tokenAmount}"
];
// (1,2) = 4 + 2 = 6
oauthUpExtTemplates[7] = [
"Sign-up",
"{string}",
"on",
"device",
"{uint}",
"until",
"timestamp",
"{uint}",
"for",
"{tokenAmount}",
"{tokenAmount}"
];
// (1,3) = 4 + 3 = 7
oauthUpExtTemplates[8] = [
"Sign-up",
"{string}",
"on",
"device",
"{uint}",
"until",
"timestamp",
"{uint}",
"for",
"{tokenAmount}",
"{tokenAmount}",
"{tokenAmount}"
];
defaultExtensions[3] = abi.encode(
"OauthSignupExtension",
address(oauthUpExt),
Expand Down Expand Up @@ -401,6 +478,7 @@ contract Deploy is Script {
console.log("AllVerifiers implementation deployed at: %s", address(verifierImpl));
console.log("ECDSAOwnedDKIMRegistry deployed at: %s", address(dkim));
console.log("Wallet implementation deployed at: %s", address(walletImpl));
console.log("Oauth core deployed at: %s", address(oauthCore));
console.log("RelayerHandler proxy deployed at: %s", address(relayerHandler));
console.log("RelayerHandler implementation deployed at: %s", address(relayerHandlerImpl));
console.log("ExtensionHandler proxy deployed at: %s", address(extensionHandler));
Expand Down
40 changes: 40 additions & 0 deletions packages/contracts/script/UpgradeOauthCore.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import "forge-std/Script.sol";
import "forge-std/console.sol";
import "../src/utils/OauthCore.sol";

contract Deploy is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
if (deployerPrivateKey == 0) {
console.log("PRIVATE_KEY env var not set");
return;
}

address oauthCore = vm.envAddress("OAUTH_CORE");
if (oauthCore == address(0)) {
console.log("OAUTH_CORE env var not set. Deploy OAUTH_CORE and set env var");
return;
}

vm.startBroadcast(deployerPrivateKey);

OauthCore oauthCoreImpl = new OauthCore();

OauthCore oauthCoreProxy = OauthCore(payable(address(oauthCore)));
oauthCoreProxy.upgradeTo(address(oauthCoreImpl));

// If you want to call some v2 function, refer to the following steps
//
// TokenRegistryV2 tokenRegistryV2 = TokenRegistryV2(address(tokenRegistry));
// address usdc = tokenRegistry.getTokenAddress(0, "USDC");

vm.stopBroadcast();

console.log("OauthCore implementation deployed at: %s", address(oauthCoreImpl));
console.log("---- DONE ----");
}
}
2 changes: 1 addition & 1 deletion packages/contracts/src/EmailWalletCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ contract EmailWalletCore is Initializable, UUPSUpgradeable, OwnableUpgradeable {
require(_getFeeConversionRate(emailOp.feeTokenName) != 0, "unsupported fee token");
require(emailOp.feePerGas <= maxFeePerGas, "fee per gas too high");
require(emailNullifiers[emailOp.emailNullifier] == false, "email nullified");
require(accountHandler.emailNullifiers(emailOp.emailNullifier) == false, "email nullified");
// require(accountHandler.emailNullifiers(emailOp.emailNullifier) == false, "email nullified");
require(
accountHandler.isDKIMPublicKeyHashValid(
emailOp.accountSalt,
Expand Down
3 changes: 2 additions & 1 deletion packages/contracts/src/Wallet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ contract Wallet is TokenCallbackHandler, OwnableUpgradeable, UUPSUpgradeable {
target != address(core.relayerHandler()) &&
target != address(core.accountHandler()) &&
target != address(core.extensionHandler()) &&
target != address(oauth),
target != address(oauth) &&
target != address(this),
"invalid target"
);
TokenRegistry tokenRegistry = core.tokenRegistry();
Expand Down
74 changes: 74 additions & 0 deletions packages/contracts/src/extensions/OauthExtensionBase.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {Extension} from "../interfaces/Extension.sol";
import {EmailWalletCore} from "../EmailWalletCore.sol";
import {Wallet} from "../Wallet.sol";
import "../interfaces/Types.sol";
import {StringUtils} from "../libraries/StringUtils.sol";
import {IOauth} from "../interfaces/IOauth.sol";
import {TokenRegistry} from "../utils/TokenRegistry.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";

abstract contract OauthExtensionBase is Extension, Initializable, UUPSUpgradeable, OwnableUpgradeable {
using StringUtils for *;

EmailWalletCore public core;

modifier onlyCore() {
require((msg.sender == address(core)) || (msg.sender == address(core.unclaimsHandler())), "invalid sender");
_;
}

constructor() {
_disableInitializers();
}

function initialize(address coreAddr) public virtual initializer {
__Ownable_init();
core = EmailWalletCore(payable(coreAddr));
}

function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}

function _decomposeTo3Bits(uint8 idx) internal pure returns (bool[3] memory) {
bool[3] memory bits;
bits[0] = (idx & 4) != 0;
bits[1] = (idx & 2) != 0;
bits[2] = (idx & 1) != 0;
return bits;
}

function _parseSigninSubjectParams(
uint8 templateIndex,
bytes[] memory subjectParams
) internal view returns (uint256 nonce, uint256 expiry, TokenAllowance[] memory tokenAllowances) {
bool[3] memory bits = _decomposeTo3Bits(templateIndex);
nonce = abi.decode(subjectParams[1], (uint256));
uint256 lastSubjectParamIdx = 2;
uint8 numTokenAllowances = 2 * uint8(bits[1] ? 1 : 0) + uint8(bits[2] ? 1 : 0);
tokenAllowances = new TokenAllowance[](numTokenAllowances);
if (bits[0]) {
expiry = abi.decode(subjectParams[lastSubjectParamIdx], (uint256));
lastSubjectParamIdx++;
} else {
expiry = type(uint256).max;
}
uint256 tokenAmount;
string memory tokenName;
TokenRegistry tokenRegistry = core.tokenRegistry();
for (uint8 i = 0; i < numTokenAllowances; i++) {
(tokenAmount, tokenName) = abi.decode(subjectParams[lastSubjectParamIdx], (uint256, string));
require(tokenAmount > 0, "invalid tokenAmount");
tokenAllowances[i] = TokenAllowance({
tokenAddr: tokenRegistry.getTokenAddress(tokenName),
amount: tokenAmount
});
lastSubjectParamIdx++;
}
require(lastSubjectParamIdx == subjectParams.length, "invalid subjectParams length");
}
}
80 changes: 10 additions & 70 deletions packages/contracts/src/extensions/OauthSigninExtension.sol
Original file line number Diff line number Diff line change
@@ -1,36 +1,22 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {Extension} from "../interfaces/Extension.sol";
import {EmailWalletCore} from "../EmailWalletCore.sol";
import {Wallet} from "../Wallet.sol";
import "../interfaces/Types.sol";
import {StringUtils} from "../libraries/StringUtils.sol";
import {OauthExtensionBase} from "./OauthExtensionBase.sol";
import {IOauth} from "../interfaces/IOauth.sol";
import {TokenRegistry} from "../utils/TokenRegistry.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "forge-std/console.sol";

contract OauthSigninExtension is Extension, Initializable, UUPSUpgradeable, OwnableUpgradeable {
using StringUtils for *;

EmailWalletCore public core;
contract OauthSigninExtension is OauthExtensionBase {
string[][] public templates;

modifier onlyCore() {
require((msg.sender == address(core)) || (msg.sender == address(core.unclaimsHandler())), "invalid sender");
_;
}

constructor() {
_disableInitializers();
}

function initialize(address coreAddr) public initializer {
__Ownable_init();
core = EmailWalletCore(payable(coreAddr));
function initialize(address coreAddr) public override initializer {
super.initialize(coreAddr);
templates = new string[][](8);
// (0,0) = 0
templates[0] = ["Sign-in", "{string}", "on", "device", "{uint}"];
Expand Down Expand Up @@ -108,12 +94,11 @@ contract OauthSigninExtension is Extension, Initializable, UUPSUpgradeable, Owna
require(!hasEmailRecipient, "recipient is not supported");

IOauth oauthCore = Wallet(payable(wallet)).getOauth();
(
string memory username,
uint256 nonce,
uint256 expiry,
TokenAllowance[] memory tokenAllowances
) = _parseSigninSubjectParams(templateIndex, subjectParams);
string memory username = abi.decode(subjectParams[0], (string));
(uint256 nonce, uint256 expiry, TokenAllowance[] memory tokenAllowances) = _parseSigninSubjectParams(
templateIndex,
subjectParams
);
bytes memory data = abi.encodeWithSignature(
"signin(string,uint256,uint256,(address,uint256)[])",
username,
Expand All @@ -123,49 +108,4 @@ contract OauthSigninExtension is Extension, Initializable, UUPSUpgradeable, Owna
);
core.executeAsExtension(address(oauthCore), data);
}

function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}

function _decomposeTo3Bits(uint8 idx) public pure returns (bool[3] memory) {
bool[3] memory bits;
bits[0] = (idx & 4) != 0;
bits[1] = (idx & 2) != 0;
bits[2] = (idx & 1) != 0;
return bits;
}

function _parseSigninSubjectParams(
uint8 templateIndex,
bytes[] memory subjectParams
)
private
view
returns (string memory username, uint256 nonce, uint256 expiry, TokenAllowance[] memory tokenAllowances)
{
bool[3] memory bits = _decomposeTo3Bits(templateIndex);
username = abi.decode(subjectParams[0], (string));
nonce = abi.decode(subjectParams[1], (uint256));
uint8 numTokenAllowances = 2 * uint8(bits[1] ? 1 : 0) + uint8(bits[2] ? 1 : 0);
tokenAllowances = new TokenAllowance[](numTokenAllowances);
uint256 lastSubjectParamIdx = 2;
if (bits[0]) {
expiry = abi.decode(subjectParams[lastSubjectParamIdx], (uint256));
lastSubjectParamIdx++;
} else {
expiry = type(uint256).max;
}
uint256 tokenAmount;
string memory tokenName;
TokenRegistry tokenRegistry = core.tokenRegistry();
for (uint8 i = 0; i < numTokenAllowances; i++) {
(tokenAmount, tokenName) = abi.decode(subjectParams[lastSubjectParamIdx], (uint256, string));
require(tokenAmount > 0, "invalid tokenAmount");
tokenAllowances[i] = TokenAllowance({
tokenAddr: tokenRegistry.getTokenAddress(tokenName),
amount: tokenAmount
});
lastSubjectParamIdx++;
}
require(lastSubjectParamIdx == subjectParams.length, "invalid subjectParams length");
}
}
Loading

0 comments on commit d118f14

Please sign in to comment.